├── .gitignore ├── doc ├── lldb1.png ├── lldb2.png ├── lldb3.png ├── machoview1.png ├── machoview2.png ├── machoview3.png ├── machoview4.png ├── machoview5.png └── all.md ├── test ├── bin │ └── TestApp └── TestApp │ ├── TestApp.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj │ └── TestApp │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.m │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ └── AppDelegate.m ├── toolchain ├── DSYMCreator ├── objc-symbols ├── IDAScript │ └── all.idc └── macho-dump.py ├── .gitmodules ├── src └── DSYMCreator │ ├── DSYMCreator │ ├── gflags │ │ ├── lib │ │ │ └── libgflags.a │ │ └── include │ │ │ ├── google │ │ │ ├── gflags.h │ │ │ └── gflags_completions.h │ │ │ └── gflags │ │ │ ├── gflags_declare.h │ │ │ └── gflags_completions.h │ ├── common.h │ ├── dwarf_debug_abbrev_section.h │ ├── dwarf_dummy_debug_line_section.h │ ├── symbol.h │ ├── util.cpp │ ├── string_table.h │ ├── exception.cpp │ ├── exception.h │ ├── string_table.cpp │ ├── dwarf_dummy_debug_line_section.cpp │ ├── dwarf_debug_abbrev_section.cpp │ ├── symbol_table.h │ ├── mach-o │ │ ├── arm64 │ │ │ └── reloc.h │ │ ├── fat.h │ │ ├── arm │ │ │ └── reloc.h │ │ ├── ranlib.h │ │ ├── arch.h │ │ ├── swap.h │ │ ├── compact_unwind_encoding.h │ │ ├── x86_64 │ │ │ └── reloc.h │ │ ├── reloc.h │ │ └── nlist.h │ ├── dwarf_debug_info_section.h │ ├── util.h │ ├── main.mm │ ├── macho_type_wrapper.h │ ├── macho.h │ └── dwarf.h │ └── DSYMCreator.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── LICENSE ├── README.md └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata/ 2 | ignore/ 3 | -------------------------------------------------------------------------------- /doc/lldb1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/lldb1.png -------------------------------------------------------------------------------- /doc/lldb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/lldb2.png -------------------------------------------------------------------------------- /doc/lldb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/lldb3.png -------------------------------------------------------------------------------- /test/bin/TestApp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/test/bin/TestApp -------------------------------------------------------------------------------- /doc/machoview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/machoview1.png -------------------------------------------------------------------------------- /doc/machoview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/machoview2.png -------------------------------------------------------------------------------- /doc/machoview3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/machoview3.png -------------------------------------------------------------------------------- /doc/machoview4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/machoview4.png -------------------------------------------------------------------------------- /doc/machoview5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/doc/machoview5.png -------------------------------------------------------------------------------- /toolchain/DSYMCreator: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/toolchain/DSYMCreator -------------------------------------------------------------------------------- /toolchain/objc-symbols: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/toolchain/objc-symbols -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/objc-symbols"] 2 | path = src/objc-symbols 3 | url = https://github.com/0xced/class-dump.git 4 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/gflags/lib/libgflags.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imoldman/DSYMCreator/HEAD/src/DSYMCreator/DSYMCreator/gflags/lib/libgflags.a -------------------------------------------------------------------------------- /test/TestApp/TestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // common.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 1/5/17. 6 | // 7 | // 8 | 9 | #ifndef common_h 10 | #define common_h 11 | 12 | #include 13 | 14 | typedef std::vector ByteBuffer; 15 | 16 | #endif /* common_h */ 17 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TestApp 4 | // 5 | // Created by oldman on 9/2/16. 6 | // Copyright © 2016 oldman. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TestApp 4 | // 5 | // Created by oldman on 9/2/16. 6 | // Copyright © 2016 oldman. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TestApp 4 | // 5 | // Created by oldman on 9/2/16. 6 | // Copyright © 2016 oldman. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf_debug_abbrev_section.h: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf_debug_abbrev_section.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #ifndef dwarf_debug_abbrev_section_h 10 | #define dwarf_debug_abbrev_section_h 11 | 12 | #include "common.h" 13 | 14 | struct DwarfDebugAbbrevSection { 15 | ByteBuffer dump() const; 16 | }; 17 | 18 | #endif /* dwarf_debug_abbrev_section_h */ 19 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf_dummy_debug_line_section.h: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf_dummy_debug_line_section.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #ifndef dwarf_dummy_debug_line_section_h 10 | #define dwarf_dummy_debug_line_section_h 11 | 12 | #include "common.h" 13 | 14 | struct DwarfDummyDebugLineSection { 15 | ByteBuffer dump() const; 16 | }; 17 | 18 | #endif /* dwarf_dummy_debug_line_section_h */ 19 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/symbol.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 8/31/16. 6 | // 7 | // 8 | 9 | #ifndef symbol_h 10 | #define symbol_h 11 | 12 | #include 13 | 14 | template 15 | struct Symbol { 16 | std::string name; 17 | T base; // base address 18 | T end; // end address 19 | 20 | Symbol(std::string name, T base, T end) : name(name), base(base), end(end) {} 21 | }; 22 | 23 | #endif /* symbol_h */ 24 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/util.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/9/15. 3 | // 4 | 5 | #include "util.h" 6 | 7 | namespace util { 8 | std::string build_string(std::function f) { 9 | std::ostringstream ss; 10 | f(ss); 11 | return ss.str(); 12 | } 13 | 14 | template <> 15 | void append_to_buffer(ByteBuffer& buffer, const ByteBuffer& buffer2) { 16 | buffer.insert(buffer.end(), buffer2.begin(), buffer2.end()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /toolchain/IDAScript/all.idc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static print_all_method(filename) { 4 | auto file = fopen(filename, "w"); 5 | if (file != 0) { 6 | auto addr = 0; 7 | for (addr = NextFunction(addr); addr != BADADDR; addr = NextFunction(addr)) { 8 | auto name = GetFunctionName(addr); 9 | auto end = GetFunctionAttr(addr, FUNCATTR_END); 10 | Message("0x%x\t0x%x\t%s\n", addr, end, name); 11 | fprintf(file, "0x%x\t0x%x\t%s\n", addr, end, name); 12 | } 13 | } 14 | fclose(file); 15 | } 16 | 17 | static main() { 18 | Wait(); 19 | print_all_method(ARGV[1]); 20 | Exit(0); 21 | } 22 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/string_table.h: -------------------------------------------------------------------------------- 1 | // 2 | // string_table.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 8/10/16. 6 | // 7 | // 8 | 9 | #ifndef __DSYMCreatore__string_table__ 10 | #define __DSYMCreatore__string_table__ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "common.h" 18 | 19 | struct StringTable { 20 | struct DumpResult { 21 | ByteBuffer buffer; 22 | std::map name_to_offset; 23 | }; 24 | DumpResult dump(const std::vector& names) const; 25 | }; 26 | 27 | #endif /* __DSYMCreatore__string_table__ */ 28 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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 | } -------------------------------------------------------------------------------- /test/TestApp/TestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/string_table.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // string_table.cpp 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 8/10/16. 6 | // 7 | // 8 | 9 | #include "string_table.h" 10 | 11 | #include 12 | 13 | StringTable::DumpResult StringTable::dump(const std::vector& names) const{ 14 | uint32_t needed_length = 0; 15 | for (const auto& n: names) { 16 | needed_length += n.size() + 1; // don't forget trailing zero 17 | } 18 | 19 | StringTable::DumpResult result; 20 | result.buffer.resize(needed_length); 21 | 22 | uint32_t current_offset = 0; 23 | for (const auto& n: names) { 24 | result.name_to_offset[n] = current_offset; 25 | memcpy(&result.buffer[current_offset], &n[0], n.length()); 26 | current_offset += n.length(); 27 | current_offset++; // skip trailing zero 28 | } 29 | 30 | assert(current_offset == needed_length); 31 | 32 | return result; 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 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 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf_dummy_debug_line_section.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf_dummy_debug_line_section.c 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #include "dwarf_dummy_debug_line_section.h" 10 | 11 | #include 12 | #include "macho_type_wrapper.h" 13 | #include "util.h" 14 | 15 | ByteBuffer DwarfDummyDebugLineSection::dump() const { 16 | // simply, we can only dump an empty debug line section to cheat lldb, 17 | // but an empty section makes lldb log some noisy message in stdout, 18 | // so here we make a normal debug line section, but without any data 19 | DwarfDebugLine section; 20 | memset(§ion, 0, sizeof(section)); // DWARFDebugLine isn't align to uint32_t, so we clear it at first 21 | section.total_length = sizeof(DwarfDebugLine) - sizeof(DwarfDebugLine::total_length); 22 | section.version = 2; 23 | section.prologue_length = section.total_length - sizeof(DwarfDebugLine::version) - sizeof(DwarfDebugLine::prologue_length); 24 | section.min_inst_length = 1; 25 | section.default_is_stmt = 1; 26 | section.line_base = 0; 27 | section.line_range = 0; 28 | section.opcode_base = 1; 29 | 30 | ByteBuffer result; 31 | util::append_to_buffer(result, section); 32 | return result; 33 | } 34 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf_debug_abbrev_section.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf_debug_abbrev_section.c 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #include "dwarf_debug_abbrev_section.h" 10 | 11 | #include 12 | #include "dwarf.h" 13 | 14 | // dump key value in abbrev section 15 | ByteBuffer DwarfDebugAbbrevSection::dump() const { 16 | // since all the value we used can be narrowed to one byte, 17 | // so we don't need encode data with LEB128, see DataExtractor.cpp in lldb project 18 | ByteBuffer result; 19 | 20 | // header 21 | result.push_back(1); // index 22 | result.push_back(DW_TAG_compile_unit), result.push_back(DW_CHILDREN_yes); 23 | result.push_back(DW_AT_language), result.push_back(DW_FORM_data2); // source code language 24 | result.push_back(0), result.push_back(0); // end flag 25 | 26 | // content, all the content use the same layout 27 | result.push_back(2); // index 28 | result.push_back(DW_TAG_subprogram), result.push_back(DW_CHILDREN_no); 29 | result.push_back(DW_AT_low_pc), result.push_back(DW_FORM_addr); 30 | result.push_back(DW_AT_high_pc), result.push_back(DW_FORM_addr); 31 | result.push_back(DW_AT_name), result.push_back(DW_FORM_strp); 32 | result.push_back(0), result.push_back(0); // end flag 33 | 34 | return result; 35 | } 36 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/symbol_table.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_table.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 8/31/16. 6 | // 7 | // 8 | 9 | #ifndef symbol_table_h 10 | #define symbol_table_h 11 | 12 | #include 13 | #include 14 | 15 | #include "common.h" 16 | #include "macho_type_wrapper.h" 17 | #include "util.h" 18 | #include "string_table.h" 19 | #include "symbol.h" 20 | 21 | 22 | template 23 | struct SymbolTable { 24 | ByteBuffer dump(const std::vector>& symbols, 25 | const std::map& name_to_offset) const; 26 | }; 27 | 28 | template 29 | ByteBuffer SymbolTable::dump(const std::vector>& symbols, 30 | const std::map& name_to_offset) const{ 31 | ByteBuffer result; 32 | for (const auto& s: symbols) { 33 | Nlist nlist; 34 | auto it = name_to_offset.find(s.name); 35 | assert(it != name_to_offset.end()); 36 | nlist.n_un.n_strx = it->second; 37 | nlist.n_type = N_SECT; 38 | nlist.n_sect = 1; // since we only have one dummy section 39 | nlist.n_desc = std::is_same::value ? 0 : N_ARM_THUMB_DEF; // under 64 bit, there is no thumb mode 40 | nlist.n_value = s.base; 41 | util::append_to_buffer(result, nlist); 42 | } 43 | 44 | return result; 45 | } 46 | 47 | #endif /* symbol_table_h */ 48 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TestApp 4 | // 5 | // Created by oldman on 9/2/16. 6 | // Copyright © 2016 oldman. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | @property (nonatomic, weak) IBOutlet UITextField* passwordTextField; 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (IBAction)verifyClick:(id)sender 18 | { 19 | NSString* text = self.passwordTextField.text; 20 | [self foo:text]; 21 | } 22 | 23 | - (BOOL)textFieldShouldReturn:(UITextField *)textField 24 | { 25 | [textField resignFirstResponder]; 26 | return NO; 27 | } 28 | 29 | - (void)foo:(NSString*)text 30 | { 31 | NSString* lastStr = [text substringWithRange:NSMakeRange(text.length - 1, 1)]; 32 | [self foo1:[text componentsSeparatedByString:@"-"] :lastStr]; 33 | } 34 | 35 | - (void)foo1:(NSArray*)array :(NSString*)text 36 | { 37 | [self foo2:array[0] :text]; 38 | } 39 | 40 | - (void)foo2:(NSString*)text : (NSString*)text2 41 | { 42 | [self foo3:[text stringByAppendingString:text2]]; 43 | } 44 | 45 | - (void)foo3:(NSString*)text 46 | { 47 | if (![text isEqualToString:@"22"]) { 48 | UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Error" message:@"Verify Failed" preferredStyle:UIAlertControllerStyleAlert]; 49 | [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; 50 | [self presentViewController:alert animated:YES completion:nil]; 51 | } 52 | } 53 | 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSYMCreator 2 | Symbol restore tool for iOS apps whose debug info are stripped. 3 | 4 | With IDA Pro's help, it can create a DSYM/DWARF file. You can import the symbol file to `lldb` by yourself. 5 | 6 | **Please Note.** If the executable binary is fetched from `App Store`, it likely is encrypted, you should decrypt the `armv7` part first by [dumpdecrypted](https://github.com/stefanesser/dumpdecrypted). 7 | 8 | ## Usage (default mode) 9 | 10 | 1. **Install IDA Pro.** The tool needs IDA Pro. So You should install it first. If you don't want to use IDA Pro, see **Usage (only-objc mode)** 11 | 12 | **Demo version is enough!** It's free, you can download from [here](https://www.hex-rays.com/products/ida/support/download_demo.shtml). 13 | 14 | 15 | 2. **Create Symbol File.** 16 | 17 | ```shell 18 | $ ./main.py --input /path/to/binary/xxx 19 | ``` 20 | 21 | Well done! Now your task in only wait (and wait, and wait...). Then a symbol file `/path/to/binary/xxx.symbol` will be created. 22 | 23 | Then you can import it to `lldb` by yourself. Have fun! 24 | 25 | ## Usage (only-objc mode) 26 | 27 | If you don't want to use IDA Pro, you can use this mode. In this mode, you don't install any software, just create symbol file like this. 28 | 29 | ```shell 30 | $ ./main.py --only-objc --input /path/to/binary/xxx 31 | ``` 32 | 33 | Also, a symbol file `/path/to/binary/xxx.symbol` will be created. 34 | 35 | Please note, since it only dumps objective-c functions, the function count in symbole file is less than the function count in symbol file created in default mode (i.e. IDA Pro mode). 36 | 37 | 38 | --- 39 | 注: 40 | 41 | Technical Doc : [高效逆向 - 为任意iOS App生成符号表](https://github.com/imoldman/DSYMCreator/blob/master/doc/all.md) 42 | 43 | 44 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TestApp 4 | // 5 | // Created by oldman on 9/2/16. 6 | // Copyright © 2016 oldman. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf_debug_info_section.h: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf_debug_info_section.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #ifndef dwarf_debug_info_section_h 10 | #define dwarf_debug_info_section_h 11 | 12 | #include 13 | 14 | #include "common.h" 15 | #include "dwarf.h" 16 | #include "symbol.h" 17 | #include "util.h" 18 | 19 | template 20 | struct DwarfDebugInfoSection { 21 | ByteBuffer dump(const std::vector>& symbols, 22 | const std::map& name_to_offset) const; 23 | }; 24 | 25 | // see DWARFDebugInfoEntry.cpp in lldb project 26 | template 27 | ByteBuffer DwarfDebugInfoSection::dump(const std::vector>& symbols, const std::map& name_to_offset) const 28 | { 29 | // since all the value we used can be narrowed to one byte, 30 | // so we don't need encode data with LEB128, see DataExtractor.cpp in lldb project 31 | ByteBuffer buffer; 32 | 33 | // header 34 | util::append_to_buffer(buffer, 0); // length, will be filled at the end of this function; 35 | util::append_to_buffer(buffer, 2); // version 36 | util::append_to_buffer(buffer, 0); // abbr_offset 37 | util::append_to_buffer(buffer, sizeof(T)); // addr_size 38 | 39 | // compile unit header 40 | util::append_to_buffer(buffer, 1); // index in abbrev section 41 | util::append_to_buffer(buffer, DW_LANG_ObjC); // language 42 | 43 | // functions 44 | for (const auto& s: symbols) { 45 | util::append_to_buffer(buffer, 2); // index in abbrev section 46 | util::append_to_buffer(buffer, s.base); // start address 47 | util::append_to_buffer(buffer, s.end); // end address 48 | auto it = name_to_offset.find(s.name); 49 | assert(it != name_to_offset.end()); 50 | util::append_to_buffer(buffer, it->second); // name offset in __dwarf_str section 51 | } 52 | 53 | util::append_to_buffer(buffer, 0); // empty compile uint header 54 | 55 | // fill length 56 | *(uint32_t*)(&buffer[0]) = (uint32_t)(buffer.size() - sizeof(uint32_t)); 57 | 58 | return buffer; 59 | } 60 | 61 | #endif /* dwarf_debug_info_section_h */ 62 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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 | #include "common.h" 13 | #include "exception.h" 14 | 15 | namespace util { 16 | std::string build_string(std::function f); 17 | 18 | template 19 | void read(FILE* file, T from, T size, void* buffer); 20 | 21 | template 22 | void write(FILE* file, T from, T size, void* buffer); 23 | 24 | template 25 | void read(const std::string& file, T from, T size, void* buffer); 26 | 27 | template 28 | void write(const std::string& file, T from, T size, void* buffer); 29 | 30 | template 31 | void append_to_buffer(ByteBuffer& buffer, const T& t); 32 | template <> 33 | void append_to_buffer(ByteBuffer& buffer, const ByteBuffer& t); 34 | 35 | 36 | // implementation 37 | template 38 | void read(FILE* file, T from, T size, void* buffer) { 39 | int err = fseek(file, from, SEEK_SET); 40 | if (err == 0) { 41 | size_t readed_size = fread(buffer, sizeof(char), size, file); 42 | if (size == readed_size) { 43 | return; 44 | } 45 | } 46 | throw Exception(ExceptionCode::kReadFailed, util::build_string([=](std::ostringstream& ss) { 47 | ss << "read failed, from: " << from << ", size: " << size; 48 | })); 49 | } 50 | 51 | template 52 | void write(FILE* file, T from, T size, void* buffer) { 53 | int err = fseek(file, from, SEEK_SET); 54 | if (err == 0) { 55 | size_t wroted_size = fwrite(buffer, sizeof(char), size, file); 56 | if (size == wroted_size) { 57 | return; 58 | } 59 | } 60 | throw Exception(ExceptionCode::kWriteFailed, util::build_string([=](std::ostringstream& ss) { 61 | ss << "write failed, from: " << from << ", size: " << size; 62 | })); 63 | } 64 | 65 | template 66 | void read(const std::string& file, T from, T size, void* buffer) { 67 | FILE* handler = fopen(file.c_str(), "rb"); 68 | if (handler == NULL) { 69 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 70 | ss << "open file failed, file: " << file << ", errno: " << errno; 71 | })); 72 | } 73 | return read(handler, from, size, buffer); 74 | } 75 | 76 | template 77 | void write(const std::string& file, T from, T size, void* buffer) { 78 | FILE* handler = fopen(file.c_str(), "wb"); 79 | if (handler == NULL) { 80 | throw Exception(ExceptionCode::kShouldNotOccur, util::build_string([&](std::ostringstream& ss) { 81 | ss << "write file failed, file: " << file << ", errno: " << errno; 82 | })); 83 | } 84 | return write(handler, from, size, buffer); 85 | } 86 | 87 | template 88 | void append_to_buffer(ByteBuffer& buffer, const T& t) { 89 | buffer.insert(buffer.end(), (uint8_t*)&t, (uint8_t*)(&t+1)); 90 | } 91 | } 92 | #endif /* defined(__insert_dylib_to_macho__util__) */ 93 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/main.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Created by oldman on 6/8/15. 3 | // 4 | 5 | #import 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "common.h" 13 | #include "exception.h" 14 | #include "util.h" 15 | #include "macho.h" 16 | 17 | DEFINE_string(uuid, "", "uuid for application binary"); 18 | DEFINE_string(raw_ida_symbol, "", "file path for the output by the ida script"); 19 | DEFINE_string(output, "", "file path to save the symbol"); 20 | DEFINE_string(dwarf_section_vmbase, "", "vm base addr for dwarf sections, in hex format"); 21 | DEFINE_bool(arm64, false, "build 64 bit symbol file (ARM64)"); 22 | 23 | namespace { 24 | void init_gflag_config(int& argc, char**& argv) { 25 | std::string usage("recreate the symbol file from ida output for ios application, e.g.\n"); 26 | usage += std::string("\n") + argv[0] + " --uuid \"14494083-a184-31e2-946b-3f942a402952\" --raw_ida_symbol \"/tmp/symbols.txt\" --dwarf_section_vmbase 0x40000 --output \"/path/to/save/loadable_symbol\" \n"; 27 | usage += std::string("then if no error occurs, a fresh symbol file will be created at /path/to/save/loadable_symbol"); 28 | ::google::SetUsageMessage(usage); 29 | 30 | ::google::ParseCommandLineFlags(&argc, &argv, true); 31 | 32 | if (FLAGS_uuid.length() == 0 || 33 | FLAGS_raw_ida_symbol.length() == 0 || 34 | FLAGS_dwarf_section_vmbase.length() == 0 || 35 | FLAGS_output.length() == 0) { 36 | ::google::ShowUsageWithFlags(argv[0]); 37 | throw Exception(ExceptionCode::kParamInvalid, "invalid param, please check the usage"); 38 | } 39 | } 40 | 41 | std::string build_failed_result(const Exception& exception) { 42 | return util::build_string([&](std::ostringstream& ss) { 43 | ss << "{\"error\":" << (int)exception.code() << ", \"description\":\"" << exception.description() << "\"}"; 44 | }); 45 | } 46 | 47 | template 48 | std::vector> read_raw_symbol_data_from_path(const std::string& path) { 49 | NSError* error = nil; 50 | NSString* content = [NSString stringWithContentsOfFile:[NSString stringWithUTF8String:path.c_str()] encoding:NSUTF8StringEncoding error:&error]; 51 | assert(error == nil); 52 | NSArray* lines = [content componentsSeparatedByString:@"\n"]; 53 | std::vector> symbols; 54 | for (NSString* line in lines) { 55 | if (line.length > 0) { 56 | NSArray* parts = [line componentsSeparatedByString:@"\t"]; 57 | assert(parts.count == 3); 58 | std::string name([parts[2] UTF8String]); 59 | T base = (T)std::stoull(std::string([parts[0] UTF8String]), nullptr, 16); 60 | T end = (T)std::stoull(std::string([parts[1] UTF8String]), nullptr, 16);; 61 | symbols.push_back(Symbol(name, base, end)); 62 | } 63 | } 64 | return symbols; 65 | } 66 | 67 | template 68 | void dump_symbol_to_file(const std::string& uuid, 69 | const std::string& symbol_file_path, 70 | T vmbase, 71 | const std::string& output_file_path) { 72 | Macho macho; 73 | auto symbols = read_raw_symbol_data_from_path(symbol_file_path); 74 | auto buffer = macho.dump(uuid, symbols, vmbase); 75 | util::write(output_file_path, 0, (T)buffer.size(), &buffer[0]); 76 | std::cout << "create symbol file success: " << output_file_path << std::endl; 77 | } 78 | } 79 | 80 | int main(int argc, char* argv[]) { 81 | 82 | try { 83 | init_gflag_config(argc, argv); 84 | 85 | if (FLAGS_arm64) { 86 | uint64_t vmbase = std::stoull(FLAGS_dwarf_section_vmbase, nullptr, 16); 87 | dump_symbol_to_file(FLAGS_uuid, FLAGS_raw_ida_symbol, vmbase, FLAGS_output); 88 | } else { 89 | uint32_t vmbase = (uint32_t)std::stoul(FLAGS_dwarf_section_vmbase, nullptr, 16); 90 | dump_symbol_to_file(FLAGS_uuid, FLAGS_raw_ida_symbol, vmbase, FLAGS_output); 91 | } 92 | return 0; 93 | } catch (Exception& e) { 94 | std::cerr << build_failed_result(e) << std::endl; 95 | return (int)e.code(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /test/TestApp/TestApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/macho_type_wrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // macho_type_wrapper.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 1/6/17. 6 | // 7 | // 8 | 9 | #ifndef macho_type_wrapper_h 10 | #define macho_type_wrapper_h 11 | 12 | #include 13 | #include 14 | #include "mach-o/loader.h" 15 | #include "nlist.h" 16 | 17 | namespace internal { 18 | struct Nlist32 : public nlist {}; 19 | struct Nlist64 : public nlist_64 {}; 20 | } 21 | 22 | template 23 | using Nlist = typename std::conditional< 24 | std::is_same::value, 25 | internal::Nlist64, 26 | internal::Nlist32 27 | >::type; 28 | 29 | namespace internal { 30 | struct MachHeader32 : public mach_header { 31 | MachHeader32() { 32 | magic = MH_MAGIC; 33 | cputype = CPU_TYPE_ARM; 34 | cpusubtype = CPU_SUBTYPE_ARM_V7; 35 | filetype = MH_DSYM; 36 | flags = 0; 37 | } 38 | }; 39 | 40 | struct MachHeader64 : public mach_header_64 { 41 | MachHeader64() { 42 | magic = MH_MAGIC_64; 43 | cputype = CPU_TYPE_ARM64; 44 | cpusubtype = CPU_SUBTYPE_ARM64_ALL; 45 | filetype = MH_DSYM; 46 | flags = 0; 47 | } 48 | }; 49 | } 50 | 51 | template 52 | using MachHeader = typename std::conditional< 53 | std::is_same::value, 54 | internal::MachHeader64, 55 | internal::MachHeader32 56 | >::type; 57 | 58 | struct UUIDCommand : public uuid_command { 59 | UUIDCommand() { 60 | cmd = LC_UUID; 61 | cmdsize = 24; 62 | } 63 | }; 64 | 65 | struct SymtabCommand : public symtab_command { 66 | SymtabCommand() { 67 | cmd = LC_SYMTAB; 68 | cmdsize = 24; 69 | } 70 | }; 71 | 72 | namespace internal { 73 | struct SegmentCommand32 : public segment_command {}; 74 | struct SegmentCommand64 : public segment_command_64 {}; 75 | 76 | template 77 | using SegmentCommand64Or32 = typename std::conditional< 78 | std::is_same::value, 79 | SegmentCommand64, 80 | SegmentCommand32 81 | >::type; 82 | 83 | template 84 | struct SegmentCommand : public SegmentCommand64Or32 { 85 | SegmentCommand() { 86 | this->cmd = std::is_same::value ? LC_SEGMENT_64 : LC_SEGMENT; 87 | this->vmsize = 0; // no need to fill, since lldb doesn't use it 88 | this->fileoff = 0; 89 | this->filesize = 0; 90 | this->initprot = VM_PROT_READ | VM_PROT_EXECUTE; 91 | this->maxprot = VM_PROT_READ | VM_PROT_EXECUTE; 92 | this->flags = 0; 93 | } 94 | }; 95 | } 96 | 97 | template 98 | struct TextSegmentCommand : public internal::SegmentCommand { 99 | TextSegmentCommand() { 100 | memset(this->segname, 0, sizeof(this->segname)); 101 | memcpy(this->segname, "__TEXT", 6); 102 | // text segment base address, must equal to the value in binary, TODO: configurable 103 | this->vmaddr = std::is_same::value ? 0x100000000 : 0x4000; 104 | } 105 | }; 106 | 107 | template 108 | struct DwarfSegmentCommand : public internal::SegmentCommand { 109 | DwarfSegmentCommand() { 110 | memset(this->segname, 0, sizeof(this->segname)); 111 | memcpy(this->segname, "__DWARF", 7); 112 | } 113 | }; 114 | 115 | namespace internal { 116 | struct Section32 : public section {}; 117 | struct Section64 : public section_64 {}; 118 | 119 | template 120 | using Section64Or32 = typename std::conditional< 121 | std::is_same::value, 122 | Section64, 123 | Section32 124 | >::type; 125 | 126 | template 127 | struct Section : public Section64Or32 { 128 | Section() { 129 | this->flags = 0; 130 | this->reserved1 = 0; 131 | this->reserved2 = 0; 132 | } 133 | }; 134 | } 135 | 136 | template 137 | struct TextSectionHeader : public internal::Section { 138 | TextSectionHeader() { 139 | memset(this->sectname, 0, sizeof(this->sectname)); 140 | memcpy(this->sectname, "__text", 6); 141 | memset(this->segname, 0, sizeof(this->segname)); 142 | memcpy(this->segname, "__TEXT", 6); 143 | this->addr = 0; // no need to fill, since lldb doesn't use it 144 | this->size = 0; // no need to fill, since lldb doesn't use it 145 | this->offset = 0; 146 | this->align = 0x3; 147 | this->reloff = 0; 148 | this->nreloc = 0; 149 | } 150 | }; 151 | 152 | template 153 | struct DwarfCommonSectionHeader : public internal::Section { 154 | DwarfCommonSectionHeader(const std::string& section_name, T vmbase, uint32_t file_offset, T length) { 155 | memset(this->sectname, 0, sizeof(this->sectname)); 156 | memcpy(this->sectname, section_name.c_str(), section_name.size()); 157 | memset(this->segname, 0, sizeof(this->segname)); 158 | memcpy(this->segname, "__DWARF", 7); 159 | this->addr = vmbase + file_offset; 160 | this->size = length; 161 | this->offset = file_offset; 162 | this->align = 0; 163 | this->reloff = 0; 164 | this->nreloc = 0; 165 | } 166 | }; 167 | 168 | // modified from lldb project, DWARFDebugLine.h/cpp 169 | struct DwarfDebugLine { 170 | uint32_t total_length; 171 | uint16_t version; 172 | uint32_t prologue_length; 173 | uint8_t min_inst_length; 174 | uint8_t default_is_stmt; 175 | int8_t line_base; 176 | uint8_t line_range; 177 | uint8_t opcode_base; 178 | }; 179 | 180 | #endif /* macho_type_wrapper_h */ 181 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/macho.h: -------------------------------------------------------------------------------- 1 | // 2 | // macho.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 8/10/16. 6 | // 7 | // 8 | 9 | #ifndef macho_h 10 | #define macho_h 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "common.h" 19 | #include "dwarf_debug_abbrev_section.h" 20 | #include "dwarf_debug_info_section.h" 21 | #include "dwarf_dummy_debug_line_section.h" 22 | #include "symbol.h" 23 | #include "symbol_table.h" 24 | #include "string_table.h" 25 | #include "util.h" 26 | 27 | template 28 | struct Macho { 29 | public: 30 | ByteBuffer dump(const std::string& uuid, 31 | const std::vector>& symbols, 32 | T section_vm_addr_offset) const; 33 | 34 | private: 35 | template 36 | static U align_to(U address, uint32_t align) { 37 | return ((address - 1) / align + 1) * align; 38 | } 39 | 40 | static const uint32_t kSymbolTableOffset = 0x1000; 41 | static const uint32_t kAlignBase = 0x1000; 42 | }; 43 | 44 | 45 | template 46 | ByteBuffer Macho::dump(const std::string& uuid, 47 | const std::vector>& symbols, 48 | T section_vm_addr_offset) const { 49 | // prepare strings 50 | std::vector names; 51 | std::transform(symbols.begin(), symbols.end(), std::inserter(names, names.end()), [](const Symbol& s) { 52 | return s.name; 53 | }); 54 | 55 | // prepare string table 56 | StringTable string_table; 57 | auto string_result = string_table.dump(names); 58 | 59 | // preapre symbol table 60 | SymbolTable symbol_table; 61 | auto symbol_buffer = symbol_table.dump(symbols, string_result.name_to_offset); 62 | 63 | // prepare dwarf sections 64 | DwarfDummyDebugLineSection debug_line_section; 65 | auto debug_line_buffer = debug_line_section.dump(); 66 | DwarfDebugAbbrevSection debug_abbrev_section; 67 | auto debug_abbrev_buffer = debug_abbrev_section.dump(); 68 | DwarfDebugInfoSection debug_info_section; 69 | auto debug_info_buffer = debug_info_section.dump(symbols, string_result.name_to_offset); 70 | 71 | // prepare symtab command 72 | SymtabCommand symtab_command; 73 | symtab_command.symoff = kSymbolTableOffset; 74 | symtab_command.nsyms = uint32_t(symbols.size()); 75 | symtab_command.stroff = uint32_t(symtab_command.symoff + symbol_buffer.size()); 76 | symtab_command.strsize = uint32_t(string_result.buffer.size()); 77 | 78 | // prepare text segment command 79 | TextSectionHeader text_section_header; 80 | TextSegmentCommand text_segment_command; 81 | text_segment_command.nsects = 1; 82 | text_segment_command.cmdsize = sizeof(TextSectionHeader) + sizeof(TextSegmentCommand); 83 | 84 | // prepare dwarf segement command 85 | T vmbase = align_to(section_vm_addr_offset, kAlignBase); 86 | uint32_t dwarf_sections_start_offset = align_to(symtab_command.stroff + symtab_command.strsize, kAlignBase); 87 | uint32_t offset = dwarf_sections_start_offset; 88 | DwarfCommonSectionHeader debug_line_section_header("__debug_line", vmbase, offset, (uint32_t)debug_line_buffer.size()); 89 | offset += debug_line_buffer.size(); 90 | DwarfCommonSectionHeader debug_info_section_header("__debug_info", vmbase, offset, (uint32_t)debug_info_buffer.size()); 91 | offset += debug_info_buffer.size(); 92 | DwarfCommonSectionHeader debug_abbrev_section_header("__debug_abbrev", vmbase, offset, (uint32_t)debug_abbrev_buffer.size()); 93 | offset += debug_abbrev_buffer.size(); 94 | DwarfCommonSectionHeader debug_str_section_header("__debug_str", vmbase, offset, (uint32_t)string_result.buffer.size()); 95 | offset += string_result.buffer.size(); 96 | 97 | DwarfSegmentCommand dwarf_segment_command; 98 | dwarf_segment_command.vmaddr = vmbase + dwarf_sections_start_offset; 99 | dwarf_segment_command.fileoff = dwarf_sections_start_offset; 100 | dwarf_segment_command.filesize = offset - dwarf_sections_start_offset; 101 | dwarf_segment_command.nsects = 4; 102 | dwarf_segment_command.cmdsize = sizeof(DwarfSegmentCommand) + 4 * sizeof(DwarfCommonSectionHeader); 103 | 104 | // prepare uuid command 105 | UUIDCommand uuid_command; 106 | std::string clean_uuid = uuid; 107 | clean_uuid.erase(std::remove(clean_uuid.begin(), clean_uuid.end(), '-'), clean_uuid.end()); // remove the hyphen in uuid first 108 | assert(clean_uuid.length() == 32); 109 | for (int i = 0; i < 16; ++i) { 110 | std::string str = clean_uuid.substr(2*i, 2); 111 | uuid_command.uuid[i] = strtol(str.c_str(), NULL, 16); 112 | } 113 | 114 | // prepare mach header 115 | MachHeader mach_header; 116 | mach_header.ncmds = 4; 117 | mach_header.sizeofcmds = sizeof(UUIDCommand) + sizeof(SymtabCommand) + sizeof(TextSegmentCommand) + sizeof(TextSectionHeader); 118 | 119 | // write 120 | ByteBuffer buffer; 121 | util::append_to_buffer(buffer, mach_header); 122 | util::append_to_buffer(buffer, uuid_command); 123 | util::append_to_buffer(buffer, symtab_command); 124 | util::append_to_buffer(buffer, text_segment_command); 125 | util::append_to_buffer(buffer, text_section_header); 126 | util::append_to_buffer(buffer, dwarf_segment_command); 127 | util::append_to_buffer(buffer, debug_line_section_header); 128 | util::append_to_buffer(buffer, debug_str_section_header); 129 | util::append_to_buffer(buffer, debug_abbrev_section_header); 130 | util::append_to_buffer(buffer, debug_info_section_header); 131 | assert(buffer.size() <= kSymbolTableOffset); 132 | buffer.resize(kSymbolTableOffset); 133 | util::append_to_buffer(buffer, symbol_buffer); 134 | util::append_to_buffer(buffer, string_result.buffer); 135 | assert(buffer.size() <= dwarf_sections_start_offset); 136 | buffer.resize(dwarf_sections_start_offset); 137 | util::append_to_buffer(buffer, debug_line_buffer); 138 | util::append_to_buffer(buffer, debug_info_buffer); 139 | util::append_to_buffer(buffer, debug_abbrev_buffer); 140 | util::append_to_buffer(buffer, string_result.buffer); 141 | 142 | return buffer; 143 | } 144 | 145 | 146 | 147 | 148 | #endif /* macho_h */ 149 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # vim: set fileencoding=utf8 3 | 4 | import os 5 | import re 6 | import struct 7 | import sys 8 | import subprocess 9 | import argparse 10 | 11 | THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 12 | TOOLCHAIN_DIR = os.path.join(THIS_DIR, 'toolchain') 13 | 14 | IDA_EXE_PATH = '/Applications/idaq.app/Contents/MacOS/idaq' 15 | 16 | def run_bash(command): 17 | shell_path = '/tmp/dsym_creator_temp_shell.sh' 18 | open(shell_path, 'w').write(command) 19 | return subprocess.check_output(['bash', shell_path]).strip() 20 | 21 | def extract_raw_symbol_from_objc_symbols(binary_path, is_arm64): 22 | objc_symbols_bin_path = os.path.join(TOOLCHAIN_DIR, 'objc-symbols') 23 | arch = 'arm64' if is_arm64 else 'armv7' 24 | raw_symbols = run_bash('%s --arch %s %s | sort' % (objc_symbols_bin_path, arch, binary_path)) 25 | 26 | # format to 'base end name' 27 | symbols = [] 28 | for l in raw_symbols.split('\n'): 29 | start, name = l.split(' ', 1) 30 | start = int(start, 16) # source start is a hex string 31 | start -= 1 # result of objc-symbol has an offset, correct it 32 | if len(symbols) > 0: 33 | symbols[-1][1] = start # fill last symbol's end address 34 | symbols.append([start, 0, name]) 35 | symbols[-1][1] = symbols[-1][0] + 0x1000 # fake end address 36 | 37 | formated_raw_symbols = '\n'.join(['%s %s %s' % (hex(x[0]), hex(x[1]), x[2]) for x in symbols]) 38 | raw_symbol_path = '/tmp/dsym_creator_raw_symbol.txt' 39 | open(raw_symbol_path, 'w').write(formated_raw_symbols) 40 | return raw_symbol_path 41 | 42 | def make_sure_ida_exists(): 43 | if not os.path.exists(IDA_EXE_PATH): 44 | print >> sys.stderr, "IDA Pro is not installed at %s, please install first" % IDA_EXE_PATH 45 | sys.exit(1) 46 | 47 | def extract_thin_if_binary_is_fat(binary_path, is_arm64): 48 | magic_num = struct.unpack('> sys.stderr, 'invalid binary file: %s' % binary_path 62 | sys.exit(1) 63 | return binary_path 64 | 65 | def extract_raw_symbol_from_ida(binary_path): 66 | raw_symbol_path = '/tmp/dsym_creator_raw_symbol.txt' 67 | idc_script_path = os.path.join(TOOLCHAIN_DIR, 'IDAScript', 'all.idc') 68 | run_bash('%s -S"%s \"%s\"" %s' % (IDA_EXE_PATH, idc_script_path, raw_symbol_path, binary_path)) 69 | return raw_symbol_path 70 | 71 | def extract_uuid_from_binary(binary_path): 72 | macho_dump_path = os.path.join(TOOLCHAIN_DIR, 'macho-dump.py') 73 | uuid = run_bash('%s %s 2>/dev/null | grep uuid | egrep -o \'\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\'' % (macho_dump_path, binary_path)) 74 | return uuid 75 | 76 | def calculate_dwarf_sections_min_file_offset_from_binary(binary_path): 77 | macho_dump_path = os.path.join(TOOLCHAIN_DIR, 'macho-dump.py') 78 | dwarf_min_offset = 0x1000 79 | result = run_bash('%s %s 2>/dev/null | egrep "vm_addr|vm_size" | egrep -o "[0-9]+" | paste - -' % (macho_dump_path, binary_path)) 80 | for line in result.split('\n'): 81 | vmaddr, vmsize = line.split() 82 | offset = int(vmaddr) + int(vmsize) 83 | if dwarf_min_offset < offset: 84 | dwarf_min_offset = offset 85 | return dwarf_min_offset 86 | 87 | def dsymcreator_format_symbol(uuid, raw_ida_symbol, dwarf_section_offset, output, is_arm64): 88 | dsym_creator_path = os.path.join(TOOLCHAIN_DIR, 'DSYMCreator') 89 | command = [dsym_creator_path, 90 | '--uuid', uuid, 91 | '--raw_ida_symbol', raw_ida_symbol, 92 | '--dwarf_section_vmbase', hex(dwarf_section_offset), # DSYMCreator need a hex string 93 | '--output', output] 94 | if is_arm64: 95 | command.append('--arm64') 96 | retcode = subprocess.call(command) 97 | if retcode !=0: 98 | print >> sys.stderr, 'DSYMCreator run failed!' 99 | sys.exit(1) 100 | 101 | def main(options): 102 | binary_path = os.path.abspath(options.binary_path) 103 | binary_dir, binary_file_name = os.path.split(binary_path) 104 | output_symbol_path = os.path.join(binary_dir, '%s.symbol' % binary_file_name) 105 | 106 | raw_symbol_path = None 107 | 108 | # if input binary is a fat file, extract armv7 109 | binary_path = extract_thin_if_binary_is_fat(binary_path, options.arm64) 110 | 111 | if options.only_objc: 112 | # only objc mode, use objc-symbols output symbol 113 | # extract symbols by objc-symbols 114 | raw_symbol_path = extract_raw_symbol_from_objc_symbols(binary_path, options.arm64) 115 | else: 116 | # ida pro mode 117 | # first make sure IDA exists 118 | make_sure_ida_exists() 119 | # extract raw symbol from IDA Pro 120 | raw_symbol_path = extract_raw_symbol_from_ida(binary_path) 121 | 122 | # extract uuid fram binary file 123 | uuid = extract_uuid_from_binary(binary_path) 124 | # extract already used address ranges from binary file, then calculate the minimum offset for dsym section 125 | dwarf_sections_min_offset = calculate_dwarf_sections_min_file_offset_from_binary(binary_path) 126 | # format symbol 127 | dsymcreator_format_symbol(uuid, raw_symbol_path, dwarf_sections_min_offset, output_symbol_path, options.arm64) 128 | 129 | return 0 130 | 131 | 132 | if __name__ == '__main__': 133 | description = '''create a symbol file from a decrypted iOS binary. 134 | If you want to create the symbol file by IDA Pro (free version is enough!), then you can execute command like this. 135 | {self_name} --input /path/to/binary 136 | 137 | If you don't want to use IDA Pro, then you can use only-objc mode (function count will be less than default mode), like this. 138 | {self_name} --only-objc --input /path/to/binary 139 | 140 | Then a file named `binary.symbol` will be in /path/to directory.'''.format(self_name=sys.argv[0]) 141 | 142 | parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawDescriptionHelpFormatter,) 143 | parser.add_argument('--only-objc', action='store_true', help='only dump objc functions, if you don\'t have IDA Pro, you can use this switch') 144 | parser.add_argument('--arm64', action='store_true', help='binary is arm64 version, or you want to extract arm64 part from universal file, note that since IDA Pro demo version doesn\'t support arm64, so you need use --only-objc with this flag') 145 | parser.add_argument('--input', action='store', required=True, dest='binary_path', help='path of the binary file, which must be decrypted first') 146 | args = parser.parse_args() 147 | 148 | sys.exit(main(args)) 149 | 150 | # vim: number list tabstop=2 shiftwidth=2 expandtab 151 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator/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 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/dwarf.h: -------------------------------------------------------------------------------- 1 | // 2 | // dwarf.h 3 | // DSYMCreator 4 | // 5 | // Created by oldman on 9/1/16. 6 | // 7 | // 8 | 9 | #ifndef dwarf_h 10 | #define dwarf_h 11 | 12 | // modified from lldb project, Dwarf.h/def 13 | enum Tag: uint16_t { 14 | DW_TAG_compile_unit = 0x0011, 15 | DW_TAG_subprogram = 0x002e, 16 | }; 17 | 18 | enum Languages: uint16_t { 19 | DW_LANG_ObjC = 0x0010, 20 | DW_LANG_ObjC_plus_plus = 0x0011, 21 | }; 22 | 23 | enum Attribute : uint16_t { 24 | DW_AT_sibling = 0x01, 25 | DW_AT_location = 0x02, 26 | DW_AT_name = 0x03, 27 | DW_AT_ordering = 0x09, 28 | DW_AT_byte_size = 0x0b, 29 | DW_AT_bit_offset = 0x0c, 30 | DW_AT_bit_size = 0x0d, 31 | DW_AT_stmt_list = 0x10, 32 | DW_AT_low_pc = 0x11, 33 | DW_AT_high_pc = 0x12, 34 | DW_AT_language = 0x13, 35 | DW_AT_discr = 0x15, 36 | DW_AT_discr_value = 0x16, 37 | DW_AT_visibility = 0x17, 38 | DW_AT_import = 0x18, 39 | DW_AT_string_length = 0x19, 40 | DW_AT_common_reference = 0x1a, 41 | DW_AT_comp_dir = 0x1b, 42 | DW_AT_const_value = 0x1c, 43 | DW_AT_containing_type = 0x1d, 44 | DW_AT_default_value = 0x1e, 45 | DW_AT_inline = 0x20, 46 | DW_AT_is_optional = 0x21, 47 | DW_AT_lower_bound = 0x22, 48 | DW_AT_producer = 0x25, 49 | DW_AT_prototyped = 0x27, 50 | DW_AT_return_addr = 0x2a, 51 | DW_AT_start_scope = 0x2c, 52 | DW_AT_bit_stride = 0x2e, 53 | DW_AT_upper_bound = 0x2f, 54 | DW_AT_abstract_origin = 0x31, 55 | DW_AT_accessibility = 0x32, 56 | DW_AT_address_class = 0x33, 57 | DW_AT_artificial = 0x34, 58 | DW_AT_base_types = 0x35, 59 | DW_AT_calling_convention = 0x36, 60 | DW_AT_count = 0x37, 61 | DW_AT_data_member_location = 0x38, 62 | DW_AT_decl_column = 0x39, 63 | DW_AT_decl_file = 0x3a, 64 | DW_AT_decl_line = 0x3b, 65 | DW_AT_declaration = 0x3c, 66 | DW_AT_discr_list = 0x3d, 67 | DW_AT_encoding = 0x3e, 68 | DW_AT_external = 0x3f, 69 | DW_AT_frame_base = 0x40, 70 | DW_AT_friend = 0x41, 71 | DW_AT_identifier_case = 0x42, 72 | DW_AT_macro_info = 0x43, 73 | DW_AT_namelist_item = 0x44, 74 | DW_AT_priority = 0x45, 75 | DW_AT_segment = 0x46, 76 | DW_AT_specification = 0x47, 77 | DW_AT_static_link = 0x48, 78 | DW_AT_type = 0x49, 79 | DW_AT_use_location = 0x4a, 80 | DW_AT_variable_parameter = 0x4b, 81 | DW_AT_virtuality = 0x4c, 82 | DW_AT_vtable_elem_location = 0x4d, 83 | DW_AT_allocated = 0x4e, 84 | DW_AT_associated = 0x4f, 85 | DW_AT_data_location = 0x50, 86 | DW_AT_byte_stride = 0x51, 87 | DW_AT_entry_pc = 0x52, 88 | DW_AT_use_UTF8 = 0x53, 89 | DW_AT_extension = 0x54, 90 | DW_AT_ranges = 0x55, 91 | DW_AT_trampoline = 0x56, 92 | DW_AT_call_column = 0x57, 93 | DW_AT_call_file = 0x58, 94 | DW_AT_call_line = 0x59, 95 | DW_AT_description = 0x5a, 96 | DW_AT_binary_scale = 0x5b, 97 | DW_AT_decimal_scale = 0x5c, 98 | DW_AT_small = 0x5d, 99 | DW_AT_decimal_sign = 0x5e, 100 | DW_AT_digit_count = 0x5f, 101 | DW_AT_picture_string = 0x60, 102 | DW_AT_mutable = 0x61, 103 | DW_AT_threads_scaled = 0x62, 104 | DW_AT_explicit = 0x63, 105 | DW_AT_object_pointer = 0x64, 106 | DW_AT_endianity = 0x65, 107 | DW_AT_elemental = 0x66, 108 | DW_AT_pure = 0x67, 109 | DW_AT_recursive = 0x68, 110 | DW_AT_signature = 0x69, 111 | DW_AT_main_subprogram = 0x6a, 112 | DW_AT_data_bit_offset = 0x6b, 113 | DW_AT_const_expr = 0x6c, 114 | DW_AT_enum_class = 0x6d, 115 | DW_AT_linkage_name = 0x6e, 116 | 117 | // New in DWARF 5: 118 | DW_AT_string_length_bit_size = 0x6f, 119 | DW_AT_string_length_byte_size = 0x70, 120 | DW_AT_rank = 0x71, 121 | DW_AT_str_offsets_base = 0x72, 122 | DW_AT_addr_base = 0x73, 123 | DW_AT_ranges_base = 0x74, 124 | DW_AT_dwo_id = 0x75, 125 | DW_AT_dwo_name = 0x76, 126 | DW_AT_reference = 0x77, 127 | DW_AT_rvalue_reference = 0x78, 128 | DW_AT_macros = 0x79, 129 | DW_AT_noreturn = 0x87, 130 | 131 | DW_AT_lo_user = 0x2000, 132 | DW_AT_hi_user = 0x3fff, 133 | 134 | DW_AT_MIPS_loop_begin = 0x2002, 135 | DW_AT_MIPS_tail_loop_begin = 0x2003, 136 | DW_AT_MIPS_epilog_begin = 0x2004, 137 | DW_AT_MIPS_loop_unroll_factor = 0x2005, 138 | DW_AT_MIPS_software_pipeline_depth = 0x2006, 139 | DW_AT_MIPS_linkage_name = 0x2007, 140 | DW_AT_MIPS_stride = 0x2008, 141 | DW_AT_MIPS_abstract_name = 0x2009, 142 | DW_AT_MIPS_clone_origin = 0x200a, 143 | DW_AT_MIPS_has_inlines = 0x200b, 144 | DW_AT_MIPS_stride_byte = 0x200c, 145 | DW_AT_MIPS_stride_elem = 0x200d, 146 | DW_AT_MIPS_ptr_dopetype = 0x200e, 147 | DW_AT_MIPS_allocatable_dopetype = 0x200f, 148 | DW_AT_MIPS_assumed_shape_dopetype = 0x2010, 149 | 150 | // This one appears to have only been implemented by Open64 for 151 | // fortran and may conflict with other extensions. 152 | DW_AT_MIPS_assumed_size = 0x2011, 153 | 154 | // GNU extensions 155 | DW_AT_sf_names = 0x2101, 156 | DW_AT_src_info = 0x2102, 157 | DW_AT_mac_info = 0x2103, 158 | DW_AT_src_coords = 0x2104, 159 | DW_AT_body_begin = 0x2105, 160 | DW_AT_body_end = 0x2106, 161 | DW_AT_GNU_vector = 0x2107, 162 | DW_AT_GNU_template_name = 0x2110, 163 | 164 | DW_AT_GNU_odr_signature = 0x210f, 165 | DW_AT_GNU_macros = 0x2119, 166 | 167 | // Extensions for Fission proposal. 168 | DW_AT_GNU_dwo_name = 0x2130, 169 | DW_AT_GNU_dwo_id = 0x2131, 170 | DW_AT_GNU_ranges_base = 0x2132, 171 | DW_AT_GNU_addr_base = 0x2133, 172 | DW_AT_GNU_pubnames = 0x2134, 173 | DW_AT_GNU_pubtypes = 0x2135, 174 | DW_AT_GNU_discriminator = 0x2136, 175 | 176 | // Borland extensions. 177 | DW_AT_BORLAND_property_read = 0x3b11, 178 | DW_AT_BORLAND_property_write = 0x3b12, 179 | DW_AT_BORLAND_property_implements = 0x3b13, 180 | DW_AT_BORLAND_property_index = 0x3b14, 181 | DW_AT_BORLAND_property_default = 0x3b15, 182 | DW_AT_BORLAND_Delphi_unit = 0x3b20, 183 | DW_AT_BORLAND_Delphi_class = 0x3b21, 184 | DW_AT_BORLAND_Delphi_record = 0x3b22, 185 | DW_AT_BORLAND_Delphi_metaclass = 0x3b23, 186 | DW_AT_BORLAND_Delphi_constructor = 0x3b24, 187 | DW_AT_BORLAND_Delphi_destructor = 0x3b25, 188 | DW_AT_BORLAND_Delphi_anonymous_method = 0x3b26, 189 | DW_AT_BORLAND_Delphi_interface = 0x3b27, 190 | DW_AT_BORLAND_Delphi_ABI = 0x3b28, 191 | DW_AT_BORLAND_Delphi_return = 0x3b29, 192 | DW_AT_BORLAND_Delphi_frameptr = 0x3b30, 193 | DW_AT_BORLAND_closure = 0x3b31, 194 | 195 | // LLVM project extensions. 196 | DW_AT_LLVM_include_path = 0x3e00, 197 | DW_AT_LLVM_config_macros = 0x3e01, 198 | DW_AT_LLVM_isysroot = 0x3e02, 199 | 200 | // Apple extensions. 201 | DW_AT_APPLE_optimized = 0x3fe1, 202 | DW_AT_APPLE_flags = 0x3fe2, 203 | DW_AT_APPLE_isa = 0x3fe3, 204 | DW_AT_APPLE_block = 0x3fe4, 205 | DW_AT_APPLE_major_runtime_vers = 0x3fe5, 206 | DW_AT_APPLE_runtime_class = 0x3fe6, 207 | DW_AT_APPLE_omit_frame_ptr = 0x3fe7, 208 | DW_AT_APPLE_property_name = 0x3fe8, 209 | DW_AT_APPLE_property_getter = 0x3fe9, 210 | DW_AT_APPLE_property_setter = 0x3fea, 211 | DW_AT_APPLE_property_attribute = 0x3feb, 212 | DW_AT_APPLE_objc_complete_type = 0x3fec, 213 | DW_AT_APPLE_property = 0x3fed 214 | }; 215 | 216 | enum Form : uint16_t { 217 | // Attribute form encodings 218 | DW_FORM_addr = 0x01, 219 | DW_FORM_block2 = 0x03, 220 | DW_FORM_block4 = 0x04, 221 | DW_FORM_data2 = 0x05, 222 | DW_FORM_data4 = 0x06, 223 | DW_FORM_data8 = 0x07, 224 | DW_FORM_string = 0x08, 225 | DW_FORM_block = 0x09, 226 | DW_FORM_block1 = 0x0a, 227 | DW_FORM_data1 = 0x0b, 228 | DW_FORM_flag = 0x0c, 229 | DW_FORM_sdata = 0x0d, 230 | DW_FORM_strp = 0x0e, 231 | DW_FORM_udata = 0x0f, 232 | DW_FORM_ref_addr = 0x10, 233 | DW_FORM_ref1 = 0x11, 234 | DW_FORM_ref2 = 0x12, 235 | DW_FORM_ref4 = 0x13, 236 | DW_FORM_ref8 = 0x14, 237 | DW_FORM_ref_udata = 0x15, 238 | DW_FORM_indirect = 0x16, 239 | DW_FORM_sec_offset = 0x17, 240 | DW_FORM_exprloc = 0x18, 241 | DW_FORM_flag_present = 0x19, 242 | DW_FORM_ref_sig8 = 0x20, 243 | 244 | // Extensions for Fission proposal 245 | DW_FORM_GNU_addr_index = 0x1f01, 246 | DW_FORM_GNU_str_index = 0x1f02, 247 | 248 | // Alternate debug sections proposal (output of "dwz" tool). 249 | DW_FORM_GNU_ref_alt = 0x1f20, 250 | DW_FORM_GNU_strp_alt = 0x1f21 251 | }; 252 | 253 | enum Constants { 254 | // Children flag 255 | DW_CHILDREN_no = 0x00, 256 | DW_CHILDREN_yes = 0x01, 257 | 258 | DW_EH_PE_absptr = 0x00, 259 | DW_EH_PE_omit = 0xff, 260 | DW_EH_PE_uleb128 = 0x01, 261 | DW_EH_PE_udata2 = 0x02, 262 | DW_EH_PE_udata4 = 0x03, 263 | DW_EH_PE_udata8 = 0x04, 264 | DW_EH_PE_sleb128 = 0x09, 265 | DW_EH_PE_sdata2 = 0x0A, 266 | DW_EH_PE_sdata4 = 0x0B, 267 | DW_EH_PE_sdata8 = 0x0C, 268 | DW_EH_PE_signed = 0x08, 269 | DW_EH_PE_pcrel = 0x10, 270 | DW_EH_PE_textrel = 0x20, 271 | DW_EH_PE_datarel = 0x30, 272 | DW_EH_PE_funcrel = 0x40, 273 | DW_EH_PE_aligned = 0x50, 274 | DW_EH_PE_indirect = 0x80 275 | }; 276 | 277 | 278 | 279 | 280 | #endif /* dwarf_h */ 281 | -------------------------------------------------------------------------------- /toolchain/macho-dump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # copy from https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_28/test/Scripts/macho-dump 4 | 5 | import struct 6 | import sys 7 | import StringIO 8 | 9 | class Reader: 10 | def __init__(self, path): 11 | if path == '-': 12 | # Snarf all the data so we can seek. 13 | self.file = StringIO.StringIO(sys.stdin.read()) 14 | else: 15 | self.file = open(path,'rb') 16 | self.isLSB = None 17 | self.is64Bit = None 18 | 19 | self.string_table = None 20 | 21 | def tell(self): 22 | return self.file.tell() 23 | 24 | def seek(self, pos): 25 | self.file.seek(pos) 26 | 27 | def read(self, N): 28 | data = self.file.read(N) 29 | if len(data) != N: 30 | raise ValueError,"Out of data!" 31 | return data 32 | 33 | def read8(self): 34 | return ord(self.read(1)) 35 | 36 | def read16(self): 37 | return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0] 38 | 39 | def read32(self): 40 | # Force to 32-bit, if possible; otherwise these might be long ints on a 41 | # big-endian platform. FIXME: Why??? 42 | Value = struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0] 43 | return int(Value) 44 | 45 | def read64(self): 46 | return struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0] 47 | 48 | def registerStringTable(self, strings): 49 | if self.string_table is not None: 50 | raise ValueError,"%s: warning: multiple string tables" % sys.argv[0] 51 | 52 | self.string_table = strings 53 | 54 | def getString(self, index): 55 | if self.string_table is None: 56 | raise ValueError,"%s: warning: no string table registered" % sys.argv[0] 57 | 58 | end = self.string_table.index('\x00', index) 59 | return self.string_table[index:end] 60 | 61 | def dumpmacho(path, opts): 62 | f = Reader(path) 63 | 64 | magic = f.read(4) 65 | if magic == '\xFE\xED\xFA\xCE': 66 | f.isLSB, f.is64Bit = False, False 67 | elif magic == '\xCE\xFA\xED\xFE': 68 | f.isLSB, f.is64Bit = True, False 69 | elif magic == '\xFE\xED\xFA\xCF': 70 | f.isLSB, f.is64Bit = False, True 71 | elif magic == '\xCF\xFA\xED\xFE': 72 | f.isLSB, f.is64Bit = True, True 73 | else: 74 | raise ValueError,"Not a Mach-O object file: %r (bad magic)" % path 75 | 76 | print "('cputype', %r)" % f.read32() 77 | print "('cpusubtype', %r)" % f.read32() 78 | filetype = f.read32() 79 | print "('filetype', %r)" % filetype 80 | 81 | numLoadCommands = f.read32() 82 | print "('num_load_commands', %r)" % filetype 83 | 84 | loadCommandsSize = f.read32() 85 | print "('load_commands_size', %r)" % loadCommandsSize 86 | 87 | print "('flag', %r)" % f.read32() 88 | 89 | if f.is64Bit: 90 | print "('reserved', %r)" % f.read32() 91 | 92 | start = f.tell() 93 | 94 | print "('load_commands', [" 95 | for i in range(numLoadCommands): 96 | dumpLoadCommand(f, i, opts) 97 | print "])" 98 | 99 | if f.tell() - start != loadCommandsSize: 100 | raise ValueError,"%s: warning: invalid load commands size: %r" % ( 101 | sys.argv[0], loadCommandsSize) 102 | 103 | def dumpLoadCommand(f, i, opts): 104 | start = f.tell() 105 | 106 | print " # Load Command %r" % i 107 | cmd = f.read32() 108 | print " (('command', %r)" % cmd 109 | cmdSize = f.read32() 110 | print " ('size', %r)" % cmdSize 111 | 112 | if cmd == 1: 113 | dumpSegmentLoadCommand(f, opts, False) 114 | elif cmd == 2: 115 | dumpSymtabCommand(f, opts) 116 | elif cmd == 11: 117 | dumpDysymtabCommand(f, opts) 118 | elif cmd == 25: 119 | dumpSegmentLoadCommand(f, opts, True) 120 | elif cmd == 27: 121 | import uuid 122 | print " ('uuid', %s)" % uuid.UUID(bytes=f.read(16)) 123 | else: 124 | print >>sys.stderr,"%s: warning: unknown load command: %r" % ( 125 | sys.argv[0], cmd) 126 | f.read(cmdSize - 8) 127 | print " )," 128 | 129 | if f.tell() - start != cmdSize: 130 | raise ValueError,"%s: warning: invalid load command size: %r" % ( 131 | sys.argv[0], cmdSize) 132 | 133 | def dumpSegmentLoadCommand(f, opts, is64Bit): 134 | print " ('segment_name', %r)" % f.read(16) 135 | if is64Bit: 136 | print " ('vm_addr', %r)" % f.read64() 137 | print " ('vm_size', %r)" % f.read64() 138 | print " ('file_offset', %r)" % f.read64() 139 | print " ('file_size', %r)" % f.read64() 140 | else: 141 | print " ('vm_addr', %r)" % f.read32() 142 | print " ('vm_size', %r)" % f.read32() 143 | print " ('file_offset', %r)" % f.read32() 144 | print " ('file_size', %r)" % f.read32() 145 | print " ('maxprot', %r)" % f.read32() 146 | print " ('initprot', %r)" % f.read32() 147 | numSections = f.read32() 148 | print " ('num_sections', %r)" % numSections 149 | print " ('flags', %r)" % f.read32() 150 | 151 | print " ('sections', [" 152 | for i in range(numSections): 153 | dumpSection(f, i, opts, is64Bit) 154 | print " ])" 155 | 156 | def dumpSymtabCommand(f, opts): 157 | symoff = f.read32() 158 | print " ('symoff', %r)" % symoff 159 | nsyms = f.read32() 160 | print " ('nsyms', %r)" % nsyms 161 | stroff = f.read32() 162 | print " ('stroff', %r)" % stroff 163 | strsize = f.read32() 164 | print " ('strsize', %r)" % strsize 165 | 166 | prev_pos = f.tell() 167 | 168 | f.seek(stroff) 169 | string_data = f.read(strsize) 170 | print " ('_string_data', %r)" % string_data 171 | 172 | f.registerStringTable(string_data) 173 | 174 | f.seek(symoff) 175 | print " ('_symbols', [" 176 | for i in range(nsyms): 177 | dumpNlist32(f, i, opts) 178 | print " ])" 179 | 180 | f.seek(prev_pos) 181 | 182 | def dumpNlist32(f, i, opts): 183 | print " # Symbol %r" % i 184 | n_strx = f.read32() 185 | print " (('n_strx', %r)" % n_strx 186 | n_type = f.read8() 187 | print " ('n_type', %#x)" % n_type 188 | n_sect = f.read8() 189 | print " ('n_sect', %r)" % n_sect 190 | n_desc = f.read16() 191 | print " ('n_desc', %r)" % n_desc 192 | if f.is64Bit: 193 | n_value = f.read64() 194 | print " ('n_value', %r)" % n_value 195 | else: 196 | n_value = f.read32() 197 | print " ('n_value', %r)" % n_value 198 | print " ('_string', %r)" % f.getString(n_strx) 199 | print " )," 200 | 201 | def dumpDysymtabCommand(f, opts): 202 | print " ('ilocalsym', %r)" % f.read32() 203 | print " ('nlocalsym', %r)" % f.read32() 204 | print " ('iextdefsym', %r)" % f.read32() 205 | print " ('nextdefsym', %r)" % f.read32() 206 | print " ('iundefsym', %r)" % f.read32() 207 | print " ('nundefsym', %r)" % f.read32() 208 | print " ('tocoff', %r)" % f.read32() 209 | print " ('ntoc', %r)" % f.read32() 210 | print " ('modtaboff', %r)" % f.read32() 211 | print " ('nmodtab', %r)" % f.read32() 212 | print " ('extrefsymoff', %r)" % f.read32() 213 | print " ('nextrefsyms', %r)" % f.read32() 214 | indirectsymoff = f.read32() 215 | print " ('indirectsymoff', %r)" % indirectsymoff 216 | nindirectsyms = f.read32() 217 | print " ('nindirectsyms', %r)" % nindirectsyms 218 | print " ('extreloff', %r)" % f.read32() 219 | print " ('nextrel', %r)" % f.read32() 220 | print " ('locreloff', %r)" % f.read32() 221 | print " ('nlocrel', %r)" % f.read32() 222 | 223 | prev_pos = f.tell() 224 | 225 | f.seek(indirectsymoff) 226 | print " ('_indirect_symbols', [" 227 | for i in range(nindirectsyms): 228 | print " # Indirect Symbol %r" % i 229 | print " (('symbol_index', %#x),)," % f.read32() 230 | print " ])" 231 | 232 | f.seek(prev_pos) 233 | 234 | def dumpSection(f, i, opts, is64Bit): 235 | print " # Section %r" % i 236 | print " (('section_name', %r)" % f.read(16) 237 | print " ('segment_name', %r)" % f.read(16) 238 | if is64Bit: 239 | print " ('address', %r)" % f.read64() 240 | size = f.read64() 241 | print " ('size', %r)" % size 242 | else: 243 | print " ('address', %r)" % f.read32() 244 | size = f.read32() 245 | print " ('size', %r)" % size 246 | offset = f.read32() 247 | print " ('offset', %r)" % offset 248 | print " ('alignment', %r)" % f.read32() 249 | reloc_offset = f.read32() 250 | print " ('reloc_offset', %r)" % reloc_offset 251 | num_reloc = f.read32() 252 | print " ('num_reloc', %r)" % num_reloc 253 | print " ('flags', %#x)" % f.read32() 254 | print " ('reserved1', %r)" % f.read32() 255 | print " ('reserved2', %r)" % f.read32() 256 | if is64Bit: 257 | print " ('reserved3', %r)" % f.read32() 258 | print " )," 259 | 260 | prev_pos = f.tell() 261 | 262 | f.seek(reloc_offset) 263 | print " ('_relocations', [" 264 | for i in range(num_reloc): 265 | print " # Relocation %r" % i 266 | print " (('word-0', %#x)," % f.read32() 267 | print " ('word-1', %#x))," % f.read32() 268 | print " ])" 269 | 270 | if opts.dumpSectionData: 271 | f.seek(offset) 272 | print " ('_section_data', %r)" % f.read(size) 273 | 274 | f.seek(prev_pos) 275 | 276 | def main(): 277 | from optparse import OptionParser, OptionGroup 278 | parser = OptionParser("usage: %prog [options] {files}") 279 | parser.add_option("", "--dump-section-data", dest="dumpSectionData", 280 | help="Dump the contents of sections", 281 | action="store_true", default=False) 282 | (opts, args) = parser.parse_args() 283 | 284 | if not args: 285 | args.append('-') 286 | 287 | for arg in args: 288 | dumpmacho(arg, opts) 289 | 290 | if __name__ == '__main__': 291 | main() 292 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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 | -------------------------------------------------------------------------------- /doc/all.md: -------------------------------------------------------------------------------- 1 | # 高效逆向 - 为任意iOS App生成符号表 2 | --- 3 | 4 | ## 缘起 5 | 6 | 1. 如果你有研究其他`App`的习惯,那你一定已经知道了以下这些信息。 7 | 1. 总体来说,研究方法分为`静态分析`和`运行分析`两种。前者对可执行二进制文件本身进行分析,无需运行程序,工具如`class-dump`, `IDA Pro`等, 后者对运行起来的『进程』(而非『程序』)进行分析,工具如`Reveal`, `cycript`, `jailbreak Tweak`, `lldb`等。`IDA Pro`与`lldb`分别是两大阵营的大杀器。 8 | 2. 一般情况下,大家会先通过`Reveal`,`class-dump`等工具大致的猜测下,缩小想要重点研究的目标范围。当确认可以深入研究的时候,就可以进入`IDA Pro` + `lldb`结合分析的方式了。`IDA Pro`用来白盒观察完整逻辑,而`lldb`则可以通过**断点**, **调用堆栈**, **输出参数与返回值**等方式黑盒观察完整逻辑(并可以验证白盒下的推测,毕竟对着`IDA Pro`看上几天难免会犯一些错误) 9 | 3. 但使用`lldb`有个问题,即调试过程中你会发现如果调试的对象是系统组件,如`MessageUI.framework`(主要用于发送信息和邮件), 调用堆栈可以正常显示方法名,简单易懂。但如果你调试一个**非系统应用**,如`微信`,那么`lldb`中只会出现``MicroMessage`___lldb_unnamed_symbol36$$MicroMessage + 70`` 之类的字样,完全不知道这个函数做了什么事情,要知道**一个有意义的名字对于逆向是多么多么的重要!!** 10 | 4. 可是`IDA Pro`却可以从多个角度分析二进制文件,猜测出很多结果(比如根据`classname`与`selector`自动给对应的实现函数命名;根据函数调用指令,自动识别函数开始位置;以及通过对相关指令监控,从而确定函数的结束位置等)。这些猜测结果如果我们善加利用,便可以辅助我们的`lldb`调试过程。这个借鉴有很多思路,可以侵入,也可以外挂,本文尝试通过**将`IDA Pro`数据库内容导出成符号表**这一思路将`IDA Pro`的信息带入到`lldb`中来。 11 | 2. `2016-08-08`, `IDA Pro 6.95`发布,在 [What's new in IDA 6.95.160808](https://www.hex-rays.com/products/ida/6.95/index.shtml) 中,作者提到了其重新加入了`iOS debugger`, 真是让人眼馋的功能。从此`IDA Pro`动态分析的功能又回到了`iOS`世界中。但`IDA Pro`的授权费确实太贵,实在是买不起,怎么办呢?『自己动手,丰衣足食』,那就我们自己构建一个『简易的iOS调试器』吧(当然还是基于`lldb`)。这其中就需要我们自行讲`IDA Pro`的信息桥接到`lldb`中,本文重建符号表便是这个思路下的第一步尝试。 12 | 3. 即使你不搞逆向,也对研究其他`App`没啥兴趣。但有一种事件你要预防,虽然他是小概率事件,但一旦发生便很惨。这就是**线上版本符号表信息丢失**。我们知道现在有很多团队是自行分析崩溃日志的(而不是借助`iTunes Connect`),这就需要自己托管符号信息,上传到崩溃分析系统。而符号表信息一旦丢失,线上的崩溃便无法解开,此时如果有大面积的崩溃出现,你就只能对着一串串的内存地址干瞪眼,毫无办法。那本文提供的重建符号表的方式,也可以解决你的燃眉之急。 13 | 14 | 综上所述,便是这篇文章的成因。 15 | 16 | ## 过程简述 17 | 要实现符号表的重建,换言之,要实现从`IDA Pro`数据库到创建`dSYM`,我们按照以下内容去将整个思路走通。 18 | 19 | 1. 首先要搞清楚符号表需要什么信息,由于我们要创建的符号表内容仅仅是函数,那么其实我们只需要三个东西: `函数名称`, `起始地址`, `结束地址` 就可以了。 20 | 1. 搞清楚符号表需要什么信息之后,接下来就是`IDA Pro`数据库的信息怎么导出来的问题了。`IDA Pro`是支持编程接口的,所以我们可以写一个自动化的脚本导出我们想要的信息。在完整版`IDA Pro`中,官方提供了`Python`接口,大家可以开开心心的用`Python`来写这个自动化的脚本。 21 | 1. 但是大家还记得上文里我们提到过一个很重要的问题么?那就是**我们买不起完整版啊!!**难道这篇文章到这里就神奇般的结束了?不不,怎么可能?虽然完整版我们买不起,但是官方放出来一个[评估版](https://www.hex-rays.com/products/ida/support/download_demo.shtml)给我们使用,虽然它有很多限制,以及用着用着就弹出个框告诉你你现在用的是`demo`版本,但是最重要的是**它是免费的!!**同时它竟然还带了原生的`IDC`语言支持,虽然是精简版的,但好歹可以用。于是我们终于可以通过这个要吐槽我能吐槽它一天不带重样的语言来编写自动化脚本了。 22 | 1. `IDA Pro`的事情搞定,接下来要看看那头:`dSYM`文件到底是什么。这个很快便能发现,一个`dSYM`实际上是个`bundle`,里面除了一个简单的`plist`,最重要的就是一个二进制文件,里面存放了符号信息。 23 | 2. 那我们既然要重建符号信息,那总得知道这个符号文件是啥格式吧。观察文件的`Magic Number`(一般是起始的一两个字节),发现是`CE FA ED FE`, 即`FEEDFACE`, 是我们熟知的`Mach-O`文件格式(即使不了解通过简单的搜索也可以获取)。 24 | 3. 既然是`Mach-O`文件,那么我们就通过 [`MachOView`](https://sourceforge.net/projects/machoview/) 工具来学习一个已有的`dSYM`吧。它大概看起来是这样的。 25 | 26 | ![](./machoview1.png) 27 | 28 | 1. 眼尖的我们很快就发现一个名字叫`Symbol Table`部分,这看起来就是我们要找的符号表了,简单的分析了下(感谢`MachOView`的直观展示),其由文件头部的名为`LC_SYMTAB`的`Load Command`定义,表示一个函数符号的列表,每个符号包含如下信息: 29 | 1. **名称**。要注意,它的名称并不是直接存在`Symbol Table`中的。相替代的,它将所有的名称都存在了一个名字叫做`String Table`的部分里,然后`Symbol Table`引用了其偏移量。 30 | 1. **Section Index**。我们知道无论是`mach-o`,还是`PE`,或者是`Elf`,都是将一个可执行文件分为多个`Segment`,每个`Segment`分为多个`Section`,代码和数据便根据自己的特点放在了许多`Section`中。这里的`Section Index`即标示了这个函数代码是放在了哪个`Section`中。 31 | 1. **起始地址**。函数代码的起始地址,这里要注意的是,实际上其记录的是函数代码在**可执行文件**的偏移量,并不是进程内存的偏移量。 32 | 33 | ![](./machoview2.png) 34 | 35 | 1. 对上一步骤得到的三个数据一一攻克。 36 | 1. 首先是名称,这个没啥难度,将所有函数名称收集一下,依次以`0`分割放在`String Table`中,同时记录下偏移量以备`Symbol Table`使用即可。 37 | 2. 接下来是`Section Index`。这里有两个选择,第一,照着可执行文件抄一份`Segment`和`Section`的声明,然后建立`Symbol Table`的时候函数地址落在哪个`Section`便使用哪个`Section Index`。还有个方式就是只建立一个`Section`,然后声明下我们的函数都落在这个`Section`中,这个方法需要验证`lldb`的兼容性(毕竟符号文件和可执行文件不一致了)。 38 | 3. 最后是`起始地址`。这里没啥问题。 39 | 1. 好,`IDA Pro`数据来源搞清楚了,也理解了`dSYM`如何格式化了,那接下来是不是就可以开始重建符号表了呢?不不,还差最后一个问题要搞清楚,即**lldb如何确定一个可执行文件和一个符号文件是相符的**。如果不了解这个问题,即使我们重建了符号表,`lldb`不认我们也没办法。不过这个问题倒是不难解决,这个奥秘就在一个叫做`LC_UUID`的`Load Command`中,当`lldb`在寻找符号表时要验证这个地方记录的`UUID`,只有可执行文件和符号文件的`UUID`相同,`lldb`才会『尝试』去加载这个符号表。 40 | 41 | ![](./machoview3.png) 42 | 43 | # 实现 44 | 45 | 搞定所有事情,接下来就是实现代码将其串联起来了。代码放在了[https://github.com/imoldman/DSYMCreator](https://github.com/imoldman/DSYMCreator),简要介绍下代码组成。 46 | 47 | - `doc`内是文档,`test`是一个测试工程,这些不是主要代码部分。 48 | 49 | - `toolchain`放置了我们整个过程使用到的工具。 50 | - 其中`IDAScript`目录放置了给`IDA Pro`使用的自动化脚本。 `all.idc`就是那个将`IDA Pro`结果导出的自动化脚本,其接收一个表示存放地址的路径,然后会将每个函数的名称,起始地址,结束地址都输出到这个文件上。 51 | 52 | - 需要详细介绍的是`DSYMCreator`工具,其源码位于`src`内,我将其`build`的结果放了一份在`toolchain`里,其工作就是本文上面描述的内容。其命令行大概看起来是这样的。 53 | 54 | ```shell 55 | $ ./DSYMCreator --uuid "14494083-a184-31e2-946b-3f942a402952" --raw_ida_symbol "/tmp/symbols.txt" --dwarf_section_vmbase 0x40000 --output /path/to/save/loadable_symbol 56 | ``` 57 | 58 | 大致解释一下。 59 | - `uuid`, 即为上文中提到的可执行文件的`uuid`, 构建符号表要用到 60 | - `raw_ida_symbol` 即为从`IDA Pro`中获取的符号数据 61 | - `dwarf_section_vmbase`, 这个稍微有点复杂。由于符号文件和可执行文件描述的实际是一个程序,因此他们的`segment`和`section`要保证兼容。其中这里的一条要求就是`dwarf`数据不能跟代码数据覆盖,此参数就是用来指定`dwarf`在进程内存中的起始地址的。 62 | - `output` 顾名思义,即为导出的符号表文件。 63 | - 根目录的`main.py`是一个整合脚本,下文详述。 64 | 65 | # 如何重建 66 | 大家估计一听上面介绍就疯了,这都是啥跟啥啊?这工具到底咋用啊? 67 | 68 | 不要着急,为了照顾大家的心情,本工具在有限的条件下做足了优化,使得大家**根本就不用关心IDA Pro**是怎么使用的,所有过程都是**自动化或半自动化完成的**(之所以还有『半自动化』的,实在是条件有限,`IDA Pro`评估版限制太多,大家多体谅。。。) 69 | 70 | **以下是最终使用方式**。 71 | 72 | > 0.
如果二进制文件有壳,先将其砸掉,注意取`armv7`版本
73 | > 1.
`$ ./main.py --input /path/to/binary/xxx`
74 | > 2.
其实你的工作已经基本结束了,`IDA Pro`会自动打开并自动开始工作,然后可能需要你点两三次`OK`(这就是前面提到的『半自动化』部分),之后等待`IDA Pro`自动退出。
75 | > 3.
此时在与输入的可执行文件`xxx`同级目录下会生成一个名为`xxx.symbol`的文件,这个文件即为我们重建的符号文件。
76 | 77 | # 验证 78 | 生成了符号文件,测试一下是不是可以正常使用呢?简单期间,本文就不采用真实案例作为目标对象了。相替代的,我在`test`目录下放置了一个小工程,其中模拟了一个登陆操作,其会将密码做一定校验,如果校验出错会弹框提醒,如果校验成功,会什么都不做,我们的目标就是搞定这个函数。 79 | 80 | 0. 提前找台`32`位的越狱机器(由于`IDA Pro`评估版只支持`32`位,因此此处必须找一个`32`位的越狱机器),并提前部署好响应版本的`debugserver`。 81 | 1. 使用该越狱设备去[http://fir.im/dsymtest](http://fir.im/dsymtest) 安装这个示例工程(已经`strip`过`debug info`)。 82 | 2. 在设备上启动这个应用。`ssh`登录这台设备,并输入如下命令,让`debugserver`监听`1234`接口,等待我们连入。 83 | 84 | ```shell 85 | $ ./debugserver *:1234 -a "TestApp" #假设debugserver在当前目录 86 | ``` 87 | 88 | 2. 在`mac`上使用`lldb`,输入如下命令 89 | 90 | ```shell 91 | $ lldb 92 | (lldb) platform select remote-ios 93 | (lldb) process connect connect://192.168.2.6:1234 #假设192.168.2.6是设备的ip,输入完这个命令后需要等待一些时间 94 | (lldb) bt # 输入当前堆栈 95 | ``` 96 | 97 | 3. 在上一步骤的堆栈中,你会看到类似这样的内容。 98 | 99 | ![](./lldb1.png) 100 | 101 | 显然`main`函数没有被识别出来。这个时候我们使用下面的命令设置`UIAlertController`的断点(想观察密码校验出错弹框的调用堆栈)。 102 | 103 | ```shell 104 | (lldb) br s -r ".*UIAlertController alertControllerWithTitle.*" #给名称中包含UIAlertController alertControllerWithTitle的函数都加上断点 105 | (lldb) c # 继续执行,让程序跑起来 106 | ``` 107 | 108 | 此时我们在密码框里输入`1`(为什么要输入`1`,是因为代码是我写的,我知道怎样会验证失败,哈哈。其实这里就是一个重现步骤的问题,在真实案例中需要大家自行准备)。调试器会停下来,并提示我们命中了断点,此时我们输入如下命令 109 | 110 | ```shell 111 | (lldb) bt #观察当前的堆栈 112 | ``` 113 | 114 | 此时你会得到类似这样的结果。 115 | 116 | ![](lldb2.png) 117 | 118 | 很明显,以`TestApp`开头的符号没有被正常解析出来。 119 | 120 | 4. 现在该我们的主角登场了,新开一个终端,`ssh`到设备,输入如下命令 121 | 122 | ```shell 123 | $ ps aux | grep TestApp 124 | ``` 125 | 126 | 这一步的目的是为了获取`TestApp`的二进制文件路径,获取到了之后退出`ssh`,使用如下命令讲可执行文件复制到本地(我在仓库里放了一份二进制文件,大家也可以用这份`/test/bin/TestApp`),并重建符号表 127 | 128 | ```shell 129 | $ scp root@192.168.2.6:/var/mobile/Containers/Bundle/Application/E3636785-6885-4193-B740-D7E39F9C85BD/TestApp.app/TestApp /path/to/TestApp 130 | $ ./main.py --input /path/to/TestApp 131 | ``` 132 | 133 | 这样一个名为`/path/to/TestApp.symbol`的文件就产生了,此即为重建好的符号文件 134 | 135 | 5. 将符号文件加载到`lldb`中, 并观察调用堆栈验证。使用如下命令。 136 | 137 | ```shell 138 | (lldb) target symbols add /path/to/TestApp.symbol 139 | (lldb) bt 140 | ``` 141 | 142 | 6. 此时输入结果中包含了符号化的信息,如下图,我们的重建过程成功。 143 | 144 | ![](./lldb3.png) 145 | 146 | 7. 调用堆栈搞定了,很明显是这个 `-[ViewController foo3:]` 搞的鬼,打个断点看看他输入参数是啥吧,恩。 147 | 148 | ```shell 149 | (lldb) br s -n "-[ViewController foo3:]" 150 | Breakpoint 2: no locations (pending). 151 | WARNING: Unable to resolve breakpoint to any actual locations. 152 | ``` 153 | 154 | 我擦,什么情况?!断点打不上?什么鬼?哪里出问题了? 155 | 156 | 其实问题的原因是:**我们刚才重建的符号表根本就不是完整的,跟lldb无法完美兼容**。哪怎样才能兼容呢,这还是要从『为什么要打断点』说起。 157 | 158 | ## 为什么要打断点 159 | 160 | 我们千辛万苦制作的符号表文件可以使得`lldb`显示堆栈时正确显示函数名,但是却不能设置断点。要知道不能设置断点是个很大的遗憾。逆向时,我们常常需要在某个函数开始时设置断点。这样设置断点主要有以下几个好处。 161 | 162 | - **观察传入参数**。虽然我们可以通过`class-dump`获取函数名,也可以顺带获取函数的参数类型,但如果参数都`OC`对象,由于所有`OC`对象本质上都是一样的,所以`class-dump`只会弱弱的显示一个`id`,如下例。 163 | 164 | ```Objective-C 165 | - (id)formatUser:(id)arg1 withOptions:(id)arg2; 166 | ``` 167 | 168 | 一个`id`用处有限,比如上例,根本无法获知这个函数的参数和返回值类型是什么,那我们逆向的思路就断在这里了。此时通过`cycript`, `jailbreak tweak`, `lldb`等方式动态调试一下就很有必要。 169 | 另外,有时候只知道参数类型是没有用的,这个时候还需要知道参数的值,在函数开始时设置断点也很有用。 170 | 171 | - **观察调用堆栈**。有时候你察觉到某个函数是整个逆向过程的关键,你通过`IDA Pro`查阅了其逻辑代码,大致理解了它做什么事情之后,现在你的任务是观察它的上下游,搞定整个流程。此时你在这个函数开始的位置打个断点,然后观察其调用堆栈,就知道了到底是哪些函数调用了它,为进一步的逆向做好准备。 172 | - **找delegate**。很多时候,我们通过`IDA Pro`看代码,发现某个地方有个对`XXXDelegate`的调用,我们想深入这个里面看看,但是由于`delegate`是运行时设置进去的,所以静态分析无法直接跳转进入到`delegate`的实现。相替代的,我们可以去`class-dump`中搜索有哪些类实现了这个名为`XXXDelegate`的`Protocol`,如果这个`Protocol`实现的类的个数比较少还好说,可以一个一个的设置断点,命中哪个就是哪个。但如果这个`Protocol`实现的类的个数特别多,依次设置断点根本不可能;或者根本找不到任何一个实现了这个`Protocol`的类,断点无法设置,这两种情况都会使我们陷入困境。此时你需要使用下面的命令设置断点。 173 | 174 | ```shell 175 | (lldb) breakpoint set --selector "downloader:downloadImageFinished:" 176 | # 或简写为 177 | (lldb) br s -S "downloader:downloadImageFinished:" 178 | ``` 179 | 180 | 该命令是告诉`lldb`将『所有』`downloader:downloadImageFinished:`的`selector`对应的实现函数全部打上断点。打上断点之后,我们运行程序,触发重现流程,断点即会命中,这个时候观察下调用堆栈,就知道到底是哪个类实现了这个`Protocol` 181 | 182 | 说一千道一万,吹了这么多,还是要搞定『为什么做好符号表但是断点无法打上』的问题。 183 | 184 | ## 理论准备 185 | 186 | 先考虑下从理论上我们是不是漏掉了什么。猜测一下,当我们打断点的时候发生什么事情呢? 187 | 188 | 显然我们这里的断点都不是直接打给内存地址的,即`address breakpoint`。相反,我们打断点的时候使用了函数名,也就是说调试器在真正打断点前需要先将我们给定的函数名转化为内存地址,也就是有一个`name -> address`的对应关系。 189 | 190 | 这个过程一共有两步。 191 | 192 | 1. 从符号表中查询该`name`对应的记录,要注意,这里的记录其实是代码在可执行文件的偏移量。 193 | 2. 讲上一步骤得到的结果映射成进程内的内存地址`address`。 194 | 195 | 接下来`lldb`对这个内存打断点就可以了。 196 | 197 | 整个过程用到符号表的只有第一步,换言之只要我们有一个『存储了函数名称和代码地址』的符号表,整个问题就搞定了,我们的断点应该就可以打上了。 198 | 199 | 可现在的情况是我们确实有符号表,但也确实打不上断点。 200 | 201 | 哪里出问题了呢? 202 | 203 | ## DWARF 204 | 205 | 『解铃还须系铃人』,既然是`lldb`告诉我们断点打不上,那就看下到底它的逻辑是啥吧。所幸`lldb`全部开源,『源码面前,了无秘密』。 206 | 207 | 如何获取和构建`lldb`,大家可以在[官网](http://lldb.llvm.org/build.html)找到。这里就不详述了。总之经过大致的浏览,很快就会发现,我们的问题多半跟一个类型名称叫做`DWARF`的符号表有关。 208 | 209 | 那什么是`DWARF`呢?如果你注意观察的话,其实平时我们接触过这个名词。一个`dSYM Bundle`文件组成看起来是这样的。 210 | 211 | ```shell 212 | $ tree 213 | . 214 | └── TestApp.app.dSYM 215 | └── Contents 216 | ├── Info.plist 217 | └── Resources 218 | └── DWARF 219 | └── TestApp 220 | ``` 221 | 222 | 这里就有一个名字叫做`DWARF`的目录,暗示了`TestApp.app.dSYM`中的符号表就是`DWARF`格式。那么他跟我们自行创建的符号表有啥区别呢?我们还是通过`MachOView`来看一下。 223 | 224 | ![](./machoview4.png) 225 | 226 | 很明显,它多了一个名字叫`__DWARF`的`segment`, 其下有一堆的`section`: `__debug_info`, `__debug_line`, `__debug_str`等等。看样子这确实是跟调试有关的东西。会不会是我们缺少这些信息导致我们无法打断点呢? 227 | 228 | 还是得先搞清楚`DWARF`到底是什么东西。 229 | 230 | 经过简单的搜索,我们得知,`DWARF`实际上是一种符号表的格式,苹果的开发人员借用了这个格式来放放置调试符号。[这里](http://wiki.dwarfstd.org/index.php?title=Apple%27s_%22Lazy%22_DWARF_Scheme)还简要记录了当年他们的『心路历程』。 231 | 232 | ## 不可或缺的sections 233 | 234 | 了解完`DWARF`是什么东西,那么我们回过来看下`lldb`是怎么使用的。经过一番查阅,发现原来**必须包含`__debug_str`, `__debug_line`, `__debug_abbrev`, `__debug_info`四个`section`,`lldb`才认为这是一个合法的`DWARF`符号表**(相关代码见注1)。 235 | 236 | 那就来看看这几个`section`分别代表啥意思吧。经过源码和多种工具(如`dwarfdump`)相结合的方式,最终得到如下的成果。 237 | 238 | - **`__debug_line`**, 这个记录了源代码的行号。我们从可执行文件中显然是分析不出啥行号的,这个`section`留空就好了,反正只是骗骗`lldb`用。 239 | - **`__debug_str`**, 这个跟上一篇提到的`String Table`比较像,记录了所有需要用到的字符串,然后其他`section`使用偏移量来引用字符串。 240 | - **`__debug_abbrev`**和**`__debug_info`**。这俩是一个整体,共同合作来记录调试需要的数据,需要一起解释。 241 | 242 | 通俗的来讲,`__debug_abbrev`中记录的是`key`, `__debug_info`中记录的是`value`。我们以代码作为例子类比下,对于`uint32_t foo = 42;`, 这里可以看做是有一个名字叫做`foo`并占用了`4`字节的`key`,其`value`是`42`。那么我们可以将`foo`和`4`写入`__debug_abbrev`中,将`42`写入`__debug_abbrev`中。 243 | 244 | ## 最终实现 245 | 246 | 罗里吧嗦说了一堆,再加上根本不知道怎么说的数据结构细节,我们最终将符号表写了一份到`DWARF`段中。代码还是放在了[GitHub](https://github.com/imoldman/DSYMCreator)上,使用前文提到的方式生成符号表并导入。 247 | 248 | 现在可以打断点拉。 249 | 250 | 来张最终的符号表结构。 251 | 252 | ![](./machoview5.png) 253 | 254 | --- 255 | 注: 256 | 257 | 1. 如果真的发生了**线上版本符号文件丢失**,除了本文的工具,还有个办法。 258 | 1. 用当时的代码当时的环境,一样的配置参数,再打一个包 259 | 2. 把`UUID`改成和线上版本的一致,记得`armv7`与`arm64`位分别有一个独立的`UUID`,都要改下。这样符号表就可以直接用了 260 | 261 | 1. `lldb`中如何判断一个`DWARF`符号表文件是合法的,相关代码如下。 262 | 263 | - [SymbolFileDWARF.cpp:584-647](https://github.com/llvm-mirror/lldb/blob/master/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp#L584-L647), 这段代码枚举符号文件里的`section`,然后根据有哪些`section`来判断这个符号表支持哪些特性(这里面就是探测了正文部分提到的四个`section`)。 264 | - [SymbolFile.cpp:58-66](https://github.com/llvm-mirror/lldb/blob/master/source/Symbol/SymbolFile.cpp#L58-L66),这段代码生成了一个符号表,然后判断一下是不是支持了`kAllAbilities`(即所有特性),那到底这个`kAllAbilities`包含哪些特性呢? 265 | - [SymbolFile.h:36-45](https://github.com/llvm-mirror/lldb/blob/master/include/lldb/Symbol/SymbolFile.h#L36-L45),原来`kAllAbilities`即包含`SymbolFileDWARF.cpp`中所列的所有特性,所以,我们要支持`__debug_str`, `__debug_line`, `__debug_abbrev`, `__debug_info`四个`section`,缺一不可。 -------------------------------------------------------------------------------- /test/TestApp/TestApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F3E867E1D79D22400379E6B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E867D1D79D22400379E6B /* main.m */; }; 11 | 7F3E86811D79D22400379E6B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E86801D79D22400379E6B /* AppDelegate.m */; }; 12 | 7F3E86841D79D22400379E6B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F3E86831D79D22400379E6B /* ViewController.m */; }; 13 | 7F3E86871D79D22400379E6B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E86851D79D22400379E6B /* Main.storyboard */; }; 14 | 7F3E86891D79D22400379E6B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E86881D79D22400379E6B /* Assets.xcassets */; }; 15 | 7F3E868C1D79D22400379E6B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 7F3E86791D79D22400379E6B /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 7F3E867D1D79D22400379E6B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 21 | 7F3E867F1D79D22400379E6B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 22 | 7F3E86801D79D22400379E6B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 23 | 7F3E86821D79D22400379E6B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 24 | 7F3E86831D79D22400379E6B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 25 | 7F3E86861D79D22400379E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | 7F3E86881D79D22400379E6B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 7F3E868B1D79D22400379E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | 7F3E868D1D79D22400379E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 7F3E86761D79D22400379E6B /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 7F3E86701D79D22400379E6B = { 43 | isa = PBXGroup; 44 | children = ( 45 | 7F3E867B1D79D22400379E6B /* TestApp */, 46 | 7F3E867A1D79D22400379E6B /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | 7F3E867A1D79D22400379E6B /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 7F3E86791D79D22400379E6B /* TestApp.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | 7F3E867B1D79D22400379E6B /* TestApp */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 7F3E867F1D79D22400379E6B /* AppDelegate.h */, 62 | 7F3E86801D79D22400379E6B /* AppDelegate.m */, 63 | 7F3E86821D79D22400379E6B /* ViewController.h */, 64 | 7F3E86831D79D22400379E6B /* ViewController.m */, 65 | 7F3E86851D79D22400379E6B /* Main.storyboard */, 66 | 7F3E86881D79D22400379E6B /* Assets.xcassets */, 67 | 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */, 68 | 7F3E868D1D79D22400379E6B /* Info.plist */, 69 | 7F3E867C1D79D22400379E6B /* Supporting Files */, 70 | ); 71 | path = TestApp; 72 | sourceTree = ""; 73 | }; 74 | 7F3E867C1D79D22400379E6B /* Supporting Files */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 7F3E867D1D79D22400379E6B /* main.m */, 78 | ); 79 | name = "Supporting Files"; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 7F3E86781D79D22400379E6B /* TestApp */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 7F3E86901D79D22400379E6B /* Build configuration list for PBXNativeTarget "TestApp" */; 88 | buildPhases = ( 89 | 7F3E86751D79D22400379E6B /* Sources */, 90 | 7F3E86761D79D22400379E6B /* Frameworks */, 91 | 7F3E86771D79D22400379E6B /* Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = TestApp; 98 | productName = TestApp; 99 | productReference = 7F3E86791D79D22400379E6B /* TestApp.app */; 100 | productType = "com.apple.product-type.application"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 7F3E86711D79D22400379E6B /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0730; 109 | ORGANIZATIONNAME = oldman; 110 | TargetAttributes = { 111 | 7F3E86781D79D22400379E6B = { 112 | CreatedOnToolsVersion = 7.3.1; 113 | DevelopmentTeam = T3GF4E8HBP; 114 | }; 115 | }; 116 | }; 117 | buildConfigurationList = 7F3E86741D79D22400379E6B /* Build configuration list for PBXProject "TestApp" */; 118 | compatibilityVersion = "Xcode 3.2"; 119 | developmentRegion = English; 120 | hasScannedForEncodings = 0; 121 | knownRegions = ( 122 | en, 123 | Base, 124 | ); 125 | mainGroup = 7F3E86701D79D22400379E6B; 126 | productRefGroup = 7F3E867A1D79D22400379E6B /* Products */; 127 | projectDirPath = ""; 128 | projectRoot = ""; 129 | targets = ( 130 | 7F3E86781D79D22400379E6B /* TestApp */, 131 | ); 132 | }; 133 | /* End PBXProject section */ 134 | 135 | /* Begin PBXResourcesBuildPhase section */ 136 | 7F3E86771D79D22400379E6B /* Resources */ = { 137 | isa = PBXResourcesBuildPhase; 138 | buildActionMask = 2147483647; 139 | files = ( 140 | 7F3E868C1D79D22400379E6B /* LaunchScreen.storyboard in Resources */, 141 | 7F3E86891D79D22400379E6B /* Assets.xcassets in Resources */, 142 | 7F3E86871D79D22400379E6B /* Main.storyboard in Resources */, 143 | ); 144 | runOnlyForDeploymentPostprocessing = 0; 145 | }; 146 | /* End PBXResourcesBuildPhase section */ 147 | 148 | /* Begin PBXSourcesBuildPhase section */ 149 | 7F3E86751D79D22400379E6B /* Sources */ = { 150 | isa = PBXSourcesBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | 7F3E86841D79D22400379E6B /* ViewController.m in Sources */, 154 | 7F3E86811D79D22400379E6B /* AppDelegate.m in Sources */, 155 | 7F3E867E1D79D22400379E6B /* main.m in Sources */, 156 | ); 157 | runOnlyForDeploymentPostprocessing = 0; 158 | }; 159 | /* End PBXSourcesBuildPhase section */ 160 | 161 | /* Begin PBXVariantGroup section */ 162 | 7F3E86851D79D22400379E6B /* Main.storyboard */ = { 163 | isa = PBXVariantGroup; 164 | children = ( 165 | 7F3E86861D79D22400379E6B /* Base */, 166 | ); 167 | name = Main.storyboard; 168 | sourceTree = ""; 169 | }; 170 | 7F3E868A1D79D22400379E6B /* LaunchScreen.storyboard */ = { 171 | isa = PBXVariantGroup; 172 | children = ( 173 | 7F3E868B1D79D22400379E6B /* Base */, 174 | ); 175 | name = LaunchScreen.storyboard; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXVariantGroup section */ 179 | 180 | /* Begin XCBuildConfiguration section */ 181 | 7F3E868E1D79D22400379E6B /* Debug */ = { 182 | isa = XCBuildConfiguration; 183 | buildSettings = { 184 | ALWAYS_SEARCH_USER_PATHS = NO; 185 | CLANG_ANALYZER_NONNULL = YES; 186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 187 | CLANG_CXX_LIBRARY = "libc++"; 188 | CLANG_ENABLE_MODULES = YES; 189 | CLANG_ENABLE_OBJC_ARC = YES; 190 | CLANG_WARN_BOOL_CONVERSION = YES; 191 | CLANG_WARN_CONSTANT_CONVERSION = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_EMPTY_BODY = YES; 194 | CLANG_WARN_ENUM_CONVERSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 197 | CLANG_WARN_UNREACHABLE_CODE = YES; 198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 199 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 200 | COPY_PHASE_STRIP = NO; 201 | DEBUG_INFORMATION_FORMAT = dwarf; 202 | ENABLE_STRICT_OBJC_MSGSEND = YES; 203 | ENABLE_TESTABILITY = YES; 204 | GCC_C_LANGUAGE_STANDARD = gnu99; 205 | GCC_DYNAMIC_NO_PIC = NO; 206 | GCC_NO_COMMON_BLOCKS = YES; 207 | GCC_OPTIMIZATION_LEVEL = 0; 208 | GCC_PREPROCESSOR_DEFINITIONS = ( 209 | "DEBUG=1", 210 | "$(inherited)", 211 | ); 212 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 213 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 214 | GCC_WARN_UNDECLARED_SELECTOR = YES; 215 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 216 | GCC_WARN_UNUSED_FUNCTION = YES; 217 | GCC_WARN_UNUSED_VARIABLE = YES; 218 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 219 | MTL_ENABLE_DEBUG_INFO = YES; 220 | ONLY_ACTIVE_ARCH = YES; 221 | SDKROOT = iphoneos; 222 | }; 223 | name = Debug; 224 | }; 225 | 7F3E868F1D79D22400379E6B /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ALWAYS_SEARCH_USER_PATHS = NO; 229 | CLANG_ANALYZER_NONNULL = YES; 230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 231 | CLANG_CXX_LIBRARY = "libc++"; 232 | CLANG_ENABLE_MODULES = YES; 233 | CLANG_ENABLE_OBJC_ARC = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_CONSTANT_CONVERSION = YES; 236 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 237 | CLANG_WARN_EMPTY_BODY = YES; 238 | CLANG_WARN_ENUM_CONVERSION = YES; 239 | CLANG_WARN_INT_CONVERSION = YES; 240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 241 | CLANG_WARN_UNREACHABLE_CODE = YES; 242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 244 | COPY_PHASE_STRIP = NO; 245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 246 | ENABLE_NS_ASSERTIONS = NO; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | GCC_C_LANGUAGE_STANDARD = gnu99; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 252 | GCC_WARN_UNDECLARED_SELECTOR = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 254 | GCC_WARN_UNUSED_FUNCTION = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 257 | MTL_ENABLE_DEBUG_INFO = NO; 258 | SDKROOT = iphoneos; 259 | VALIDATE_PRODUCT = YES; 260 | }; 261 | name = Release; 262 | }; 263 | 7F3E86911D79D22400379E6B /* Debug */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 267 | CODE_SIGN_IDENTITY = "iPhone Developer"; 268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 269 | ENABLE_BITCODE = NO; 270 | INFOPLIST_FILE = TestApp/Info.plist; 271 | IPHONEOS_DEPLOYMENT_TARGET = 8; 272 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 273 | PRODUCT_BUNDLE_IDENTIFIER = li.oldman.TestApp2; 274 | PRODUCT_NAME = "$(TARGET_NAME)"; 275 | PROVISIONING_PROFILE = ""; 276 | }; 277 | name = Debug; 278 | }; 279 | 7F3E86921D79D22400379E6B /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 283 | CODE_SIGN_IDENTITY = "iPhone Developer"; 284 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 285 | DEPLOYMENT_POSTPROCESSING = YES; 286 | ENABLE_BITCODE = NO; 287 | INFOPLIST_FILE = TestApp/Info.plist; 288 | IPHONEOS_DEPLOYMENT_TARGET = 8; 289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 290 | PRODUCT_BUNDLE_IDENTIFIER = li.oldman.TestApp2; 291 | PRODUCT_NAME = "$(TARGET_NAME)"; 292 | PROVISIONING_PROFILE = ""; 293 | }; 294 | name = Release; 295 | }; 296 | /* End XCBuildConfiguration section */ 297 | 298 | /* Begin XCConfigurationList section */ 299 | 7F3E86741D79D22400379E6B /* Build configuration list for PBXProject "TestApp" */ = { 300 | isa = XCConfigurationList; 301 | buildConfigurations = ( 302 | 7F3E868E1D79D22400379E6B /* Debug */, 303 | 7F3E868F1D79D22400379E6B /* Release */, 304 | ); 305 | defaultConfigurationIsVisible = 0; 306 | defaultConfigurationName = Release; 307 | }; 308 | 7F3E86901D79D22400379E6B /* Build configuration list for PBXNativeTarget "TestApp" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 7F3E86911D79D22400379E6B /* Debug */, 312 | 7F3E86921D79D22400379E6B /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | }; 316 | /* End XCConfigurationList section */ 317 | }; 318 | rootObject = 7F3E86711D79D22400379E6B /* Project object */; 319 | } 320 | -------------------------------------------------------------------------------- /src/DSYMCreator/DSYMCreator/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/DSYMCreator/DSYMCreator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F0C95A01D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */; }; 11 | 7F0C95A31D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */; }; 12 | 7F0C95AB1D78340A0066A1F4 /* exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F0C95A91D78340A0066A1F4 /* exception.cpp */; }; 13 | 7F39B0181E1F9BB100859541 /* string_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F39B0171E1F9BB100859541 /* string_table.cpp */; }; 14 | 7F866B621D76A1430028592C /* libgflags.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F866B431D76A1430028592C /* libgflags.a */; }; 15 | 7F866B671D76A1430028592C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F866B5B1D76A1430028592C /* main.mm */; }; 16 | 7F866B681D76A1430028592C /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F866B5D1D76A1430028592C /* util.cpp */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_dummy_debug_line_section.cpp; path = DSYMCreator/dwarf_dummy_debug_line_section.cpp; sourceTree = ""; }; 21 | 7F0C959F1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_dummy_debug_line_section.h; path = DSYMCreator/dwarf_dummy_debug_line_section.h; sourceTree = ""; }; 22 | 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_debug_abbrev_section.cpp; path = DSYMCreator/dwarf_debug_abbrev_section.cpp; sourceTree = ""; }; 23 | 7F0C95A21D77D4C40066A1F4 /* dwarf_debug_abbrev_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_debug_abbrev_section.h; path = DSYMCreator/dwarf_debug_abbrev_section.h; sourceTree = ""; }; 24 | 7F0C95A61D77D9CD0066A1F4 /* dwarf_debug_info_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_debug_info_section.h; path = DSYMCreator/dwarf_debug_info_section.h; sourceTree = ""; }; 25 | 7F0C95A81D77D9DE0066A1F4 /* dwarf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dwarf.h; path = DSYMCreator/dwarf.h; sourceTree = ""; }; 26 | 7F0C95A91D78340A0066A1F4 /* exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exception.cpp; path = DSYMCreator/exception.cpp; sourceTree = SOURCE_ROOT; }; 27 | 7F0C95AA1D78340A0066A1F4 /* exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = exception.h; path = DSYMCreator/exception.h; sourceTree = SOURCE_ROOT; }; 28 | 7F39B00F1E1E4E0F00859541 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = DSYMCreator/common.h; sourceTree = ""; }; 29 | 7F39B0101E1F2F3B00859541 /* macho_type_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_type_wrapper.h; path = DSYMCreator/macho_type_wrapper.h; sourceTree = ""; }; 30 | 7F39B0171E1F9BB100859541 /* string_table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_table.cpp; path = DSYMCreator/string_table.cpp; sourceTree = ""; }; 31 | 7F866B2B1D76A0E20028592C /* DSYMCreator */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DSYMCreator; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 7F866B3B1D76A1430028592C /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; }; 33 | 7F866B3C1D76A1430028592C /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; }; 34 | 7F866B3D1D76A1430028592C /* gflags_declare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_declare.h; sourceTree = ""; }; 35 | 7F866B3F1D76A1430028592C /* gflags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags.h; sourceTree = ""; }; 36 | 7F866B401D76A1430028592C /* gflags_completions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gflags_completions.h; sourceTree = ""; }; 37 | 7F866B421D76A1430028592C /* libgflags.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags.2.dylib; sourceTree = ""; }; 38 | 7F866B431D76A1430028592C /* libgflags.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgflags.a; sourceTree = ""; }; 39 | 7F866B441D76A1430028592C /* libgflags.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags.dylib; sourceTree = ""; }; 40 | 7F866B451D76A1430028592C /* libgflags_nothreads.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags_nothreads.2.dylib; sourceTree = ""; }; 41 | 7F866B461D76A1430028592C /* libgflags_nothreads.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgflags_nothreads.a; sourceTree = ""; }; 42 | 7F866B471D76A1430028592C /* libgflags_nothreads.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libgflags_nothreads.dylib; sourceTree = ""; }; 43 | 7F866B491D76A1430028592C /* libgflags.pc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libgflags.pc; sourceTree = ""; }; 44 | 7F866B4A1D76A1430028592C /* libgflags_nothreads.pc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libgflags_nothreads.pc; sourceTree = ""; }; 45 | 7F866B4C1D76A1430028592C /* arch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arch.h; sourceTree = ""; }; 46 | 7F866B4E1D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 47 | 7F866B501D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 48 | 7F866B511D76A1430028592C /* compact_unwind_encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compact_unwind_encoding.h; sourceTree = ""; }; 49 | 7F866B521D76A1430028592C /* fat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fat.h; sourceTree = ""; }; 50 | 7F866B531D76A1430028592C /* loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loader.h; sourceTree = ""; }; 51 | 7F866B541D76A1430028592C /* nlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nlist.h; sourceTree = ""; }; 52 | 7F866B551D76A1430028592C /* ranlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ranlib.h; sourceTree = ""; }; 53 | 7F866B561D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 54 | 7F866B571D76A1430028592C /* swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; 55 | 7F866B591D76A1430028592C /* reloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reloc.h; sourceTree = ""; }; 56 | 7F866B5B1D76A1430028592C /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = DSYMCreator/main.mm; sourceTree = ""; }; 57 | 7F866B5D1D76A1430028592C /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = util.cpp; path = DSYMCreator/util.cpp; sourceTree = ""; }; 58 | 7F866B5E1D76A1430028592C /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = DSYMCreator/util.h; sourceTree = ""; }; 59 | 7F866B6B1D76A5020028592C /* string_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_table.h; path = DSYMCreator/string_table.h; sourceTree = ""; }; 60 | 7F866B6D1D76B2BD0028592C /* symbol_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = symbol_table.h; path = DSYMCreator/symbol_table.h; sourceTree = ""; }; 61 | 7F866B751D76BC0F0028592C /* macho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho.h; path = DSYMCreator/macho.h; sourceTree = ""; }; 62 | 7F866B781D76BF1A0028592C /* symbol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = symbol.h; path = DSYMCreator/symbol.h; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 7F866B281D76A0E20028592C /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | 7F866B621D76A1430028592C /* libgflags.a in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | 7F866B221D76A0E20028592C = { 78 | isa = PBXGroup; 79 | children = ( 80 | 7F866B381D76A1430028592C /* gflags */, 81 | 7F866B4B1D76A1430028592C /* mach-o */, 82 | 7F0C95A91D78340A0066A1F4 /* exception.cpp */, 83 | 7F0C95AA1D78340A0066A1F4 /* exception.h */, 84 | 7F866B5B1D76A1430028592C /* main.mm */, 85 | 7F866B5D1D76A1430028592C /* util.cpp */, 86 | 7F866B5E1D76A1430028592C /* util.h */, 87 | 7F866B781D76BF1A0028592C /* symbol.h */, 88 | 7F866B6B1D76A5020028592C /* string_table.h */, 89 | 7F39B0171E1F9BB100859541 /* string_table.cpp */, 90 | 7F866B6D1D76B2BD0028592C /* symbol_table.h */, 91 | 7F39B00F1E1E4E0F00859541 /* common.h */, 92 | 7F0C95A81D77D9DE0066A1F4 /* dwarf.h */, 93 | 7F0C959E1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp */, 94 | 7F0C959F1D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.h */, 95 | 7F0C95A11D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp */, 96 | 7F0C95A21D77D4C40066A1F4 /* dwarf_debug_abbrev_section.h */, 97 | 7F0C95A61D77D9CD0066A1F4 /* dwarf_debug_info_section.h */, 98 | 7F866B751D76BC0F0028592C /* macho.h */, 99 | 7F39B0101E1F2F3B00859541 /* macho_type_wrapper.h */, 100 | 7F866B2C1D76A0E20028592C /* Products */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | 7F866B2C1D76A0E20028592C /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 7F866B2B1D76A0E20028592C /* DSYMCreator */, 108 | ); 109 | name = Products; 110 | sourceTree = ""; 111 | }; 112 | 7F866B381D76A1430028592C /* gflags */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 7F866B391D76A1430028592C /* include */, 116 | 7F866B411D76A1430028592C /* lib */, 117 | ); 118 | name = gflags; 119 | path = DSYMCreator/gflags; 120 | sourceTree = ""; 121 | }; 122 | 7F866B391D76A1430028592C /* include */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 7F866B3A1D76A1430028592C /* gflags */, 126 | 7F866B3E1D76A1430028592C /* google */, 127 | ); 128 | path = include; 129 | sourceTree = ""; 130 | }; 131 | 7F866B3A1D76A1430028592C /* gflags */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 7F866B3B1D76A1430028592C /* gflags.h */, 135 | 7F866B3C1D76A1430028592C /* gflags_completions.h */, 136 | 7F866B3D1D76A1430028592C /* gflags_declare.h */, 137 | ); 138 | path = gflags; 139 | sourceTree = ""; 140 | }; 141 | 7F866B3E1D76A1430028592C /* google */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 7F866B3F1D76A1430028592C /* gflags.h */, 145 | 7F866B401D76A1430028592C /* gflags_completions.h */, 146 | ); 147 | path = google; 148 | sourceTree = ""; 149 | }; 150 | 7F866B411D76A1430028592C /* lib */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 7F866B421D76A1430028592C /* libgflags.2.dylib */, 154 | 7F866B431D76A1430028592C /* libgflags.a */, 155 | 7F866B441D76A1430028592C /* libgflags.dylib */, 156 | 7F866B451D76A1430028592C /* libgflags_nothreads.2.dylib */, 157 | 7F866B461D76A1430028592C /* libgflags_nothreads.a */, 158 | 7F866B471D76A1430028592C /* libgflags_nothreads.dylib */, 159 | 7F866B481D76A1430028592C /* pkgconfig */, 160 | ); 161 | path = lib; 162 | sourceTree = ""; 163 | }; 164 | 7F866B481D76A1430028592C /* pkgconfig */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | 7F866B491D76A1430028592C /* libgflags.pc */, 168 | 7F866B4A1D76A1430028592C /* libgflags_nothreads.pc */, 169 | ); 170 | path = pkgconfig; 171 | sourceTree = ""; 172 | }; 173 | 7F866B4B1D76A1430028592C /* mach-o */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 7F866B4C1D76A1430028592C /* arch.h */, 177 | 7F866B4D1D76A1430028592C /* arm */, 178 | 7F866B4F1D76A1430028592C /* arm64 */, 179 | 7F866B511D76A1430028592C /* compact_unwind_encoding.h */, 180 | 7F866B521D76A1430028592C /* fat.h */, 181 | 7F866B531D76A1430028592C /* loader.h */, 182 | 7F866B541D76A1430028592C /* nlist.h */, 183 | 7F866B551D76A1430028592C /* ranlib.h */, 184 | 7F866B561D76A1430028592C /* reloc.h */, 185 | 7F866B571D76A1430028592C /* swap.h */, 186 | 7F866B581D76A1430028592C /* x86_64 */, 187 | ); 188 | name = "mach-o"; 189 | path = "DSYMCreator/mach-o"; 190 | sourceTree = ""; 191 | }; 192 | 7F866B4D1D76A1430028592C /* arm */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | 7F866B4E1D76A1430028592C /* reloc.h */, 196 | ); 197 | path = arm; 198 | sourceTree = ""; 199 | }; 200 | 7F866B4F1D76A1430028592C /* arm64 */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | 7F866B501D76A1430028592C /* reloc.h */, 204 | ); 205 | path = arm64; 206 | sourceTree = ""; 207 | }; 208 | 7F866B581D76A1430028592C /* x86_64 */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | 7F866B591D76A1430028592C /* reloc.h */, 212 | ); 213 | path = x86_64; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXGroup section */ 217 | 218 | /* Begin PBXNativeTarget section */ 219 | 7F866B2A1D76A0E20028592C /* DSYMCreator */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = 7F866B321D76A0E20028592C /* Build configuration list for PBXNativeTarget "DSYMCreator" */; 222 | buildPhases = ( 223 | 7F866B271D76A0E20028592C /* Sources */, 224 | 7F866B281D76A0E20028592C /* Frameworks */, 225 | 7F9554E61D87D78300207AEB /* ShellScript */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | ); 231 | name = DSYMCreator; 232 | productName = DSYMCreator; 233 | productReference = 7F866B2B1D76A0E20028592C /* DSYMCreator */; 234 | productType = "com.apple.product-type.tool"; 235 | }; 236 | /* End PBXNativeTarget section */ 237 | 238 | /* Begin PBXProject section */ 239 | 7F866B231D76A0E20028592C /* Project object */ = { 240 | isa = PBXProject; 241 | attributes = { 242 | LastUpgradeCheck = 0800; 243 | TargetAttributes = { 244 | 7F866B2A1D76A0E20028592C = { 245 | CreatedOnToolsVersion = 7.3.1; 246 | }; 247 | }; 248 | }; 249 | buildConfigurationList = 7F866B261D76A0E20028592C /* Build configuration list for PBXProject "DSYMCreator" */; 250 | compatibilityVersion = "Xcode 3.2"; 251 | developmentRegion = English; 252 | hasScannedForEncodings = 0; 253 | knownRegions = ( 254 | en, 255 | ); 256 | mainGroup = 7F866B221D76A0E20028592C; 257 | productRefGroup = 7F866B2C1D76A0E20028592C /* Products */; 258 | projectDirPath = ""; 259 | projectRoot = ""; 260 | targets = ( 261 | 7F866B2A1D76A0E20028592C /* DSYMCreator */, 262 | ); 263 | }; 264 | /* End PBXProject section */ 265 | 266 | /* Begin PBXShellScriptBuildPhase section */ 267 | 7F9554E61D87D78300207AEB /* ShellScript */ = { 268 | isa = PBXShellScriptBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | ); 272 | inputPaths = ( 273 | ); 274 | outputPaths = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "echo \"cp -f \\\"${CONFIGURATION_BUILD_DIR}/DSYMCreator\\\" \\\"${SRCROOT}/../../toolchain/\\\"\"\ncp -f \"${CONFIGURATION_BUILD_DIR}/DSYMCreator\" \"${SRCROOT}/../../toolchain/\""; 279 | }; 280 | /* End PBXShellScriptBuildPhase section */ 281 | 282 | /* Begin PBXSourcesBuildPhase section */ 283 | 7F866B271D76A0E20028592C /* Sources */ = { 284 | isa = PBXSourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | 7F866B671D76A1430028592C /* main.mm in Sources */, 288 | 7F0C95A01D77C77C0066A1F4 /* dwarf_dummy_debug_line_section.cpp in Sources */, 289 | 7F39B0181E1F9BB100859541 /* string_table.cpp in Sources */, 290 | 7F866B681D76A1430028592C /* util.cpp in Sources */, 291 | 7F0C95A31D77D4C40066A1F4 /* dwarf_debug_abbrev_section.cpp in Sources */, 292 | 7F0C95AB1D78340A0066A1F4 /* exception.cpp in Sources */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | /* End PBXSourcesBuildPhase section */ 297 | 298 | /* Begin XCBuildConfiguration section */ 299 | 7F866B301D76A0E20028592C /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | CLANG_ANALYZER_NONNULL = YES; 304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 305 | CLANG_CXX_LIBRARY = "libc++"; 306 | CLANG_ENABLE_MODULES = YES; 307 | CLANG_ENABLE_OBJC_ARC = YES; 308 | CLANG_WARN_BOOL_CONVERSION = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INFINITE_RECURSION = YES; 314 | CLANG_WARN_INT_CONVERSION = YES; 315 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 316 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 317 | CLANG_WARN_UNREACHABLE_CODE = YES; 318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 319 | CODE_SIGN_IDENTITY = "-"; 320 | COPY_PHASE_STRIP = NO; 321 | DEBUG_INFORMATION_FORMAT = dwarf; 322 | ENABLE_STRICT_OBJC_MSGSEND = YES; 323 | ENABLE_TESTABILITY = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_DYNAMIC_NO_PIC = NO; 326 | GCC_NO_COMMON_BLOCKS = YES; 327 | GCC_OPTIMIZATION_LEVEL = 0; 328 | GCC_PREPROCESSOR_DEFINITIONS = ( 329 | "DEBUG=1", 330 | "$(inherited)", 331 | ); 332 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 333 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 334 | GCC_WARN_UNDECLARED_SELECTOR = YES; 335 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 336 | GCC_WARN_UNUSED_FUNCTION = YES; 337 | GCC_WARN_UNUSED_VARIABLE = YES; 338 | MACOSX_DEPLOYMENT_TARGET = 10.11; 339 | MTL_ENABLE_DEBUG_INFO = YES; 340 | ONLY_ACTIVE_ARCH = YES; 341 | SDKROOT = macosx; 342 | }; 343 | name = Debug; 344 | }; 345 | 7F866B311D76A0E20028592C /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ALWAYS_SEARCH_USER_PATHS = NO; 349 | CLANG_ANALYZER_NONNULL = YES; 350 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 351 | CLANG_CXX_LIBRARY = "libc++"; 352 | CLANG_ENABLE_MODULES = YES; 353 | CLANG_ENABLE_OBJC_ARC = YES; 354 | CLANG_WARN_BOOL_CONVERSION = YES; 355 | CLANG_WARN_CONSTANT_CONVERSION = YES; 356 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 357 | CLANG_WARN_EMPTY_BODY = YES; 358 | CLANG_WARN_ENUM_CONVERSION = YES; 359 | CLANG_WARN_INFINITE_RECURSION = YES; 360 | CLANG_WARN_INT_CONVERSION = YES; 361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 362 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 363 | CLANG_WARN_UNREACHABLE_CODE = YES; 364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 365 | CODE_SIGN_IDENTITY = "-"; 366 | COPY_PHASE_STRIP = NO; 367 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 368 | ENABLE_NS_ASSERTIONS = NO; 369 | ENABLE_STRICT_OBJC_MSGSEND = YES; 370 | GCC_C_LANGUAGE_STANDARD = gnu99; 371 | GCC_NO_COMMON_BLOCKS = YES; 372 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 374 | GCC_WARN_UNDECLARED_SELECTOR = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 376 | GCC_WARN_UNUSED_FUNCTION = YES; 377 | GCC_WARN_UNUSED_VARIABLE = YES; 378 | MACOSX_DEPLOYMENT_TARGET = 10.11; 379 | MTL_ENABLE_DEBUG_INFO = NO; 380 | SDKROOT = macosx; 381 | }; 382 | name = Release; 383 | }; 384 | 7F866B331D76A0E20028592C /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | HEADER_SEARCH_PATHS = ./DSYMCreator/gflags/include/; 388 | LIBRARY_SEARCH_PATHS = ( 389 | "$(inherited)", 390 | "$(PROJECT_DIR)/DSYMCreator/gflags/lib", 391 | ); 392 | PRODUCT_NAME = "$(TARGET_NAME)"; 393 | }; 394 | name = Debug; 395 | }; 396 | 7F866B341D76A0E20028592C /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | HEADER_SEARCH_PATHS = ./DSYMCreator/gflags/include/; 400 | LIBRARY_SEARCH_PATHS = ( 401 | "$(inherited)", 402 | "$(PROJECT_DIR)/DSYMCreator/gflags/lib", 403 | ); 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | }; 406 | name = Release; 407 | }; 408 | /* End XCBuildConfiguration section */ 409 | 410 | /* Begin XCConfigurationList section */ 411 | 7F866B261D76A0E20028592C /* Build configuration list for PBXProject "DSYMCreator" */ = { 412 | isa = XCConfigurationList; 413 | buildConfigurations = ( 414 | 7F866B301D76A0E20028592C /* Debug */, 415 | 7F866B311D76A0E20028592C /* Release */, 416 | ); 417 | defaultConfigurationIsVisible = 0; 418 | defaultConfigurationName = Release; 419 | }; 420 | 7F866B321D76A0E20028592C /* Build configuration list for PBXNativeTarget "DSYMCreator" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | 7F866B331D76A0E20028592C /* Debug */, 424 | 7F866B341D76A0E20028592C /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | /* End XCConfigurationList section */ 430 | }; 431 | rootObject = 7F866B231D76A0E20028592C /* Project object */; 432 | } 433 | --------------------------------------------------------------------------------