├── Screenshot.png ├── src ├── images │ ├── App Icon.icns │ ├── Prefs Output Icon.tif │ ├── Prefs General Icon.tif │ └── Main Window Background.tif ├── English.lproj │ ├── Help │ │ ├── art │ │ │ ├── otxArt.png │ │ │ ├── iconhelptoc.png │ │ │ └── iconhelpcenter.png │ │ ├── images │ │ │ ├── pdf.gif │ │ │ ├── up.gif │ │ │ ├── dash.gif │ │ │ ├── next.gif │ │ │ ├── bullet.gif │ │ │ ├── download.gif │ │ │ ├── previous.gif │ │ │ ├── sm_dash.gif │ │ │ ├── MainWindow.jpg │ │ │ ├── hideframes.gif │ │ │ ├── showframes.gif │ │ │ ├── sm_bullet.gif │ │ │ ├── graydiamond.gif │ │ │ ├── larg_bullet.gif │ │ │ ├── sm_triangle.gif │ │ │ └── sm_opentriangle.gif │ │ ├── Contents │ │ │ ├── chapter_2_section_5.html │ │ │ ├── chapter_2_section_3.html │ │ │ ├── chapter_2_section_11.html │ │ │ ├── chapter_2_section_12.html │ │ │ ├── chapter_2_section_4.html │ │ │ ├── chapter_2_section_6.html │ │ │ ├── chapter_2_section_7.html │ │ │ ├── chapter_2_section_10.html │ │ │ ├── chapter_2_section_2.html │ │ │ ├── chapter_2_section_8.html │ │ │ ├── index.html │ │ │ ├── index_last.html │ │ │ ├── toc_closed.html │ │ │ ├── chapter_2_section_1.html │ │ │ └── toc.html │ │ ├── Overview │ │ │ ├── index.html │ │ │ ├── chapter_1_section_2.html │ │ │ ├── index_last.html │ │ │ ├── toc_closed.html │ │ │ ├── chapter_1_section_1.html │ │ │ └── toc.html │ │ └── index.html │ └── MainMenu.nib │ │ └── keyedobjects.nib ├── source │ ├── Processors │ │ ├── ExeProcessor.h │ │ ├── ExeProcessor.m │ │ ├── PPC64Processor.h │ │ ├── X8664Processor.h │ │ ├── X86Processor.h │ │ ├── PPCProcessor.h │ │ ├── Exe64Processor.h │ │ └── Exe32Processor.h │ ├── SmoothViewAnimation.h │ ├── Categories │ │ ├── SysUtils.h │ │ ├── Searchers64.h │ │ ├── Searchers.h │ │ ├── ListUtils.h │ │ ├── List64Utils.h │ │ ├── ArchSpecifics.h │ │ ├── Arch64Specifics.h │ │ ├── Objc64Accessors.h │ │ ├── ObjcAccessors.h │ │ ├── Object64Loader.h │ │ ├── ObjectLoader.h │ │ ├── Searchers64.m │ │ ├── ArchSpecifics.m │ │ ├── Arch64Specifics.m │ │ ├── SysUtils.m │ │ ├── ListUtils.m │ │ ├── List64Utils.m │ │ ├── Searchers.m │ │ ├── Objc64Accessors.m │ │ └── ObjcAccessors.m │ ├── Protocols │ │ ├── ErrorReporter.h │ │ ├── ProgressReporter.h │ │ └── Deobfuscator.h │ ├── UserDefaultKeys.h │ ├── SharedDefs.h │ ├── CLIController.h │ ├── SystemIncludes.h │ ├── SmoothViewAnimation.m │ ├── DropBox.h │ ├── StolenDefs.h │ ├── DropBox.m │ ├── ObjcTypes.m │ ├── AppController.h │ ├── ObjcTypes.h │ └── SyscallStrings.h ├── Version.plist ├── otx_Prefix.pch ├── main.m └── Info.plist ├── .gitignore └── README.md /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/Screenshot.png -------------------------------------------------------------------------------- /src/images/App Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/images/App Icon.icns -------------------------------------------------------------------------------- /src/images/Prefs Output Icon.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/images/Prefs Output Icon.tif -------------------------------------------------------------------------------- /src/images/Prefs General Icon.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/images/Prefs General Icon.tif -------------------------------------------------------------------------------- /src/English.lproj/Help/art/otxArt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/art/otxArt.png -------------------------------------------------------------------------------- /src/English.lproj/Help/images/pdf.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/pdf.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/up.gif -------------------------------------------------------------------------------- /src/images/Main Window Background.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/images/Main Window Background.tif -------------------------------------------------------------------------------- /src/source/Processors/ExeProcessor.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/source/Processors/ExeProcessor.h -------------------------------------------------------------------------------- /src/source/Processors/ExeProcessor.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/source/Processors/ExeProcessor.m -------------------------------------------------------------------------------- /src/English.lproj/Help/images/dash.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/dash.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/next.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/next.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/art/iconhelptoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/art/iconhelptoc.png -------------------------------------------------------------------------------- /src/English.lproj/Help/images/bullet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/bullet.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/download.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/download.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/previous.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/previous.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/sm_dash.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/sm_dash.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/MainWindow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/MainWindow.jpg -------------------------------------------------------------------------------- /src/English.lproj/Help/images/hideframes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/hideframes.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/showframes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/showframes.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/sm_bullet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/sm_bullet.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/art/iconhelpcenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/art/iconhelpcenter.png -------------------------------------------------------------------------------- /src/English.lproj/Help/images/graydiamond.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/graydiamond.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/larg_bullet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/larg_bullet.gif -------------------------------------------------------------------------------- /src/English.lproj/Help/images/sm_triangle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/sm_triangle.gif -------------------------------------------------------------------------------- /src/English.lproj/MainMenu.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/MainMenu.nib/keyedobjects.nib -------------------------------------------------------------------------------- /src/English.lproj/Help/images/sm_opentriangle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x43x61x69/otx/HEAD/src/English.lproj/Help/images/sm_opentriangle.gif -------------------------------------------------------------------------------- /src/source/SmoothViewAnimation.h: -------------------------------------------------------------------------------- 1 | /* 2 | SmoothViewAnimation.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | @interface SmoothViewAnimation : NSViewAnimation 10 | { 11 | @private 12 | NSWindow* iWindow; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /src/source/Categories/SysUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | SysUtils.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | @interface NSObject(SysUtils) 10 | 11 | - (BOOL)checkOtool: (NSString*)filePath; 12 | - (NSString*)pathForTool: (NSString*)toolName; 13 | 14 | @end -------------------------------------------------------------------------------- /src/source/Protocols/ErrorReporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | ErrorReporter.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | @protocol ErrorReporter 10 | 11 | - (void)reportError: (NSString*)inMessageText 12 | suggestion: (NSString*)inInformativeText; 13 | 14 | @end -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /src/Version.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildVersion 6 | 17 7 | ProjectName 8 | NibPBTemplates 9 | SourceVersion 10 | 1150000 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/source/Protocols/ProgressReporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | ProgressReporter.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #define PRValueKey @"PRValueKey" // NSNumber* (double) 10 | #define PRIndeterminateKey @"PRIndeterminateKey" // NSNumber* (BOOL) 11 | #define PRNewLineKey @"PRNewLineKey" // NSNumber* (BOOL) 12 | #define PRCompleteKey @"PRCompleteKey" // NSNumber* (BOOL) 13 | #define PRDescriptionKey @"PRDescriptionKey" // NSString* 14 | 15 | @protocol ProgressReporter 16 | 17 | - (void)reportProgress: (NSDictionary*)inState; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /src/source/Categories/Searchers64.h: -------------------------------------------------------------------------------- 1 | /* 2 | Searchers64.h 3 | 4 | A category on Exe64Processor that contains the various binary search 5 | methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe64Processor.h" 13 | 14 | @interface Exe64Processor(Searchers64) 15 | 16 | - (char*)findSymbolByAddress: (uint64_t)inAddress; 17 | - (BOOL)findClassMethod: (Method64Info**)outMI 18 | byAddress: (UInt64)inAddress; 19 | - (BOOL)findIvar: (objc2_64_ivar_t**)outIvar 20 | inClass: (objc2_64_class_t*)inClass 21 | withOffset: (UInt64)inOffset; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /src/otx_Prefix.pch: -------------------------------------------------------------------------------- 1 | /* 2 | otx_Prefix.pch 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | extern BOOL gCancel; 10 | #endif 11 | 12 | #ifndef NSAppKitVersionNumber10_4 13 | #define NSAppKitVersionNumber10_4 824 14 | #endif 15 | 16 | #ifndef NSAppKitVersionNumber10_6 17 | #define NSAppKitVersionNumber10_6 1038 18 | #endif 19 | 20 | #define OS_IS_PRE_TIGER NSAppKitVersionNumber < NSAppKitVersionNumber10_4 21 | #define OS_IS_POST_TIGER floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_4 22 | #define OS_IS_TIGER (!OS_IS_PRE_TIGER) && (!OS_IS_POST_TIGER) 23 | #define OS_IS_PRE_SNOW NSAppKitVersionNumber < NSAppKitVersionNumber10_6 24 | -------------------------------------------------------------------------------- /src/source/Categories/Searchers.h: -------------------------------------------------------------------------------- 1 | /* 2 | Searchers.h 3 | 4 | A category on Exe32Processor that contains the various binary search 5 | methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe32Processor.h" 13 | 14 | @interface Exe32Processor(Searchers) 15 | 16 | - (char*)findSymbolByAddress: (uint32_t)inAddress; 17 | - (BOOL)findClassMethod: (MethodInfo**)outMI 18 | byAddress: (uint32_t)inAddress; 19 | - (BOOL)findCatMethod: (MethodInfo**)outMI 20 | byAddress: (uint32_t)inAddress; 21 | - (BOOL)findIvar: (objc1_32_ivar*)outIvar 22 | inClass: (objc1_32_class*)inClass 23 | withOffset: (uint32_t)inOffset; 24 | - (BOOL)findIvar: (objc2_32_ivar_t**)outIvar 25 | inClass2: (objc2_32_class_t*)inClass 26 | withOffset: (uint32_t)inOffset; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /src/source/Categories/ListUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | ListUtils.h 3 | 4 | A category on Exe32Processor that contains the linked list 5 | manipulation methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe32Processor.h" 13 | 14 | @interface Exe32Processor(ListUtils) 15 | 16 | - (void)insertLine: (Line*)inLine 17 | before: (Line*)nextLine 18 | inList: (Line**)listHead; 19 | - (void)insertLine: (Line*)inLine 20 | after: (Line*)prevLine 21 | inList: (Line**)listHead; 22 | - (void)replaceLine: (Line*)inLine 23 | withLine: (Line*)newLine 24 | inList: (Line**)listHead; 25 | - (BOOL)printLinesFromList: (Line*)listHead; 26 | - (void)deleteLinesFromList: (Line*)listHead; 27 | - (void)deleteLinesBefore: (Line*)inLine 28 | fromList: (Line**)listHead; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /src/source/Categories/List64Utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | List64Utils.h 3 | 4 | A category on Exe64Processor that contains the linked list 5 | manipulation methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe64Processor.h" 13 | 14 | @interface Exe64Processor(List64Utils) 15 | 16 | - (void)insertLine: (Line64*)inLine 17 | before: (Line64*)nextLine 18 | inList: (Line64**)listHead; 19 | - (void)insertLine: (Line64*)inLine 20 | after: (Line64*)prevLine 21 | inList: (Line64**)listHead; 22 | - (void)replaceLine: (Line64*)inLine 23 | withLine: (Line64*)newLine 24 | inList: (Line64**)listHead; 25 | - (BOOL)printLinesFromList: (Line64*)listHead; 26 | - (void)deleteLinesFromList: (Line64*)listHead; 27 | - (void)deleteLinesBefore: (Line64*)inLine 28 | fromList: (Line64**)listHead; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /src/source/Protocols/Deobfuscator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Deobfuscator.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | /* NopList 10 | 11 | 'list' is a 'count'-sized array of addresses at which an obfuscated 12 | sequence of nops was found. 13 | */ 14 | typedef struct NopList 15 | { 16 | unsigned char** list; 17 | uint32_t count; 18 | } 19 | NopList; 20 | 21 | // ============================================================================ 22 | 23 | @protocol Deobfuscator 24 | 25 | - (BOOL)verifyNops: (unsigned char***)outList 26 | numFound: (uint32_t*)outFound; 27 | - (unsigned char**)searchForNopsIn: (unsigned char*)inHaystack 28 | ofLength: (uint32_t)inHaystackLength 29 | numFound: (uint32_t*)outFound; 30 | - (NSURL*)fixNops: (NopList*)inList 31 | toPath: (NSString*)inOutputFilePath; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /src/source/Processors/PPC64Processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | PPC64Processor.h 3 | 4 | A subclass of Exe64Processor that handles PPC64-specific issues. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe64Processor.h" 12 | 13 | #define MB64(x) ((((x) >> 6) & 0x1f) | (x) & 0x20) // bits 5 - 10, split 14 | #define SH(x) ((((x) >> 12) & 0x0f) | ((x) >> 7) & 0x10) // bits 11 - 15, split 15 | #define DS(x) (SInt64)(BD((x))) // bits 2 - 15 16 | 17 | // ============================================================================ 18 | 19 | @interface PPC64Processor : Exe64Processor 20 | { 21 | GP64RegisterInfo iRegInfos[32]; 22 | GP64RegisterInfo iLR; 23 | GP64RegisterInfo iCTR; 24 | 25 | Var64Info* iLocalSelves; // 'self' copied to local variables 26 | uint32_t iNumLocalSelves; 27 | Var64Info* iLocalVars; 28 | uint32_t iNumLocalVars; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /src/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #ifdef OTX_CLI 10 | #import "CLIController.h" 11 | #else 12 | #import 13 | #endif 14 | 15 | BOOL gCancel = NO; 16 | 17 | int main( 18 | int argc, 19 | char* argv[]) 20 | { 21 | if (OS_IS_PRE_TIGER) 22 | { 23 | fprintf(stderr, "otx requires Mac OS X 10.4 or higher.\n"); 24 | return -1; 25 | } 26 | 27 | int result = 1; 28 | 29 | #ifdef OTX_CLI 30 | @autoreleasepool { 31 | CLIController* controller = 32 | [[[CLIController alloc] initWithArgs: argv count: argc] autorelease]; 33 | 34 | if (controller) 35 | { 36 | [controller processFile]; 37 | result = noErr; 38 | } 39 | else 40 | result = -1; 41 | } 42 | #else 43 | result = NSApplicationMain(argc, (const char**)argv); 44 | #endif 45 | 46 | return result; 47 | } 48 | -------------------------------------------------------------------------------- /src/source/Categories/ArchSpecifics.h: -------------------------------------------------------------------------------- 1 | /* 2 | ArchSpecifics.h 3 | 4 | A category on Exe32Processor that contains most of the 5 | architecture-specific methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe32Processor.h" 13 | 14 | @interface Exe32Processor(ArchSpecifics) 15 | 16 | - (void)gatherFuncInfos; 17 | - (void)postProcessCodeLine: (Line**)ioLine; 18 | - (BOOL)lineIsFunction: (Line*)inLine; 19 | - (BOOL)codeIsBlockJump: (UInt8*)inCode; 20 | - (void)codeFromLine: (Line*)inLine; 21 | - (void)checkThunk: (Line*)inLine; 22 | - (BOOL)getThunkInfo: (ThunkInfo*)outInfo 23 | forLine: (Line*)inLine; 24 | 25 | - (void)commentForLine: (Line*)inLine; 26 | - (void)commentForSystemCall; 27 | - (void)commentForMsgSend: (char*)ioComment 28 | fromLine: (Line*)inLine; 29 | 30 | - (void)resetRegisters: (Line*)inLine; 31 | - (void)updateRegisters: (Line*)inLine; 32 | - (BOOL)restoreRegisters: (Line*)inLine; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Show md5 checksum 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Show md5 checksum

17 |

Includes the md5 checksum of the executable file at the beginning of the output file.

18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Show data sections 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Show data sections

17 |

Prints the contents of all data sections at the end of the output file.

18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/source/Categories/Arch64Specifics.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arch64Specifics.h 3 | 4 | A category on Exe64Processor that contains most of the 5 | architecture-specific methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Exe64Processor.h" 13 | 14 | @interface Exe64Processor(Arch64Specifics) 15 | 16 | - (void)gatherFuncInfos; 17 | - (void)postProcessCodeLine: (Line64**)ioLine; 18 | - (BOOL)lineIsFunction: (Line64*)inLine; 19 | - (BOOL)codeIsBlockJump: (UInt8*)inCode; 20 | - (void)codeFromLine: (Line64*)inLine; 21 | - (void)checkThunk: (Line64*)inLine; 22 | - (BOOL)getThunkInfo: (ThunkInfo*)outInfo 23 | forLine: (Line64*)inLine; 24 | 25 | - (void)commentForLine: (Line64*)inLine; 26 | - (void)commentForSystemCall; 27 | - (void)commentForMsgSend: (char*)ioComment 28 | fromLine: (Line64*)inLine; 29 | 30 | - (void)resetRegisters: (Line64*)inLine; 31 | - (void)updateRegisters: (Line64*)inLine; 32 | - (BOOL)restoreRegisters: (Line64*)inLine; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /src/source/UserDefaultKeys.h: -------------------------------------------------------------------------------- 1 | /* 2 | UserDefaultKeys.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #define AskOutputDirKey @"AskOutputDir" 8 | #define DemangleCppNamesKey @"DemangleCppNames" 9 | #define EntabOutputKey @"EntabOutput" 10 | #define OpenOutputFileKey @"OpenOutputFile" 11 | #define OutputAppKey @"OutputApp" 12 | #define OutputFileExtensionKey @"OutputFileExtension" 13 | #define OutputFileNameKey @"OutputFileName" 14 | #define SeparateLogicalBlocksKey @"SeparateLogicalBlocks" 15 | #define ShowDataSectionKey @"ShowDataSection" 16 | #define ShowIvarTypesKey @"ShowIvarTypes" 17 | #define ShowLocalOffsetsKey @"ShowLocalOffsets" 18 | #define ShowMD5Key @"ShowMD5" 19 | #define ShowMethodReturnTypesKey @"ShowMethodReturnTypes" 20 | #define ShowReturnStatementsKey @"ShowReturnStatements" 21 | #define UseCustomNameKey @"UseCustomName" 22 | #define VerboseMsgSendsKey @"VerboseMsgSends" 23 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Location 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Location

17 |

This 18 | option instructs otx to place the output file in the same folder as the 19 | executable(or the .app package) or to ask you where to save the output 20 | file.

21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/source/SharedDefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | SharedDefs.h 3 | 4 | Definitions shared by GUI and CLI targets. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | /* ProcOptions 10 | 11 | Options for processing executables. GUI target sets these using 12 | NSUserDefaults, CLI target sets them with command line arguments. This 13 | is necessary for the CLI target to behave consistently across 14 | invocations, and to keep it from altering the GUI target's prefs. 15 | */ 16 | typedef struct 17 | { // CLI flags 18 | BOOL localOffsets; // l 19 | BOOL showCode; // C 20 | BOOL entabOutput; // e 21 | BOOL dataSections; // d 22 | BOOL checksum; // c 23 | BOOL verboseMsgSends; // m 24 | BOOL separateLogicalBlocks; // b 25 | BOOL demangleCppNames; // n 26 | BOOL returnTypes; // r 27 | BOOL variableTypes; // v 28 | BOOL returnStatements; // R 29 | BOOL debugMode; // -debug 30 | } 31 | ProcOptions; 32 | -------------------------------------------------------------------------------- /src/source/Categories/Objc64Accessors.h: -------------------------------------------------------------------------------- 1 | /* 2 | Objc64Accessors.h 3 | 4 | What the filename says. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe64Processor.h" 12 | 13 | @interface Exe64Processor(ObjcAccessors) 14 | 15 | - (BOOL)getObjcClassPtr: (objc2_64_class_t**)outClass 16 | fromMethod: (UInt64)inAddress; 17 | - (BOOL)getObjcMethod: (Method64Info**)outMI 18 | fromAddress: (UInt64)inAddress; 19 | - (BOOL)getObjcMethodList: (objc2_64_method_list_t*)outList 20 | methods: (objc2_64_method_t**)outMethods 21 | fromAddress: (UInt64)inAddress; 22 | - (BOOL)getObjcDescription: (char**)outDescription 23 | fromObject: (const char*)inObject 24 | type: (UInt8)inType; 25 | - (BOOL)getObjcClass: (objc2_64_class_t*)outClass 26 | fromName: (const char*)inName; 27 | - (BOOL)getObjcClassPtr: (objc2_64_class_t**)outClassPtr 28 | fromName: (const char*)inName; 29 | - (BOOL)getObjcMetaClass: (objc2_64_class_t*)outClass 30 | fromClass: (objc2_64_class_t*)inClass; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Open file with application 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Open file with application

17 |

If 18 | you would like otx to open the output file immediately after it is created, enter the name of your preferred viewer in this text field. Capitalization is ignored.

19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | otx Help: Entab output 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

Entab output

18 |

Replaces 19 | multiple spaces with tabs where possible. This option reduces the 20 | output file size, but may look strange depending on the application 21 | used to view the output.

22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Demangle names 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Demangle names

17 |

Attempts to revert mangled C++ symbols to their original form.

18 |

19 | _Znwm 20 |
or
21 | operator new(unsigned long) 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Show method types 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Show method types

17 |

Displays the data type of the return value of ObjC methods.

18 |

19 | -(unsigned int)[CDropBox draggingEntered:] 20 |
or
21 | -[CDropBox draggingEntered:] 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | otx 2 | === 3 | 4 | [![Author](https://img.shields.io/badge/Author-Zhi--Wei_Cai-red.svg?style=flat-square)](http://vox.vg/) ![Build](https://img.shields.io/badge/Build-566-green.svg?style=flat-square) ![SDK](https://img.shields.io/badge/SDK-10.9-yellow.svg?style=flat-square) ![License](https://img.shields.io/badge/License-Public-blue.svg?style=flat-square) 5 | 6 | The Mach-O disassembler. 7 | 8 | ![screenshot](Screenshot.png) 9 | 10 | Description 11 | ----------- 12 | 13 | This is an up-to-date version of otx. 14 | 15 | Following changes has been made: 16 | 17 | * Based on 10.9 SDK. 18 | * 64bit binary. 19 | * Works with new otool came with Xcode 4.2+. 20 | * Source code compatible with Xcode 5+. 21 | * Tons of bug fixes. 22 | 23 | 24 | Changelog 25 | --------- 26 | 27 | Build 566: 28 | 29 | * Fix the Save menu. (#4) 30 | 31 | Build 565: 32 | 33 | * Fix the Open menu. (#3) 34 | 35 | Build 564: 36 | 37 | * No more symbolic link. 38 | * Minor UI fix. 39 | 40 | Build 563: 41 | 42 | * Minor UI updates. 43 | 44 | Build 562: 45 | 46 | * Update base SDK to 10.9 and Xcode 5.1. 47 | 48 | Build 561: 49 | 50 | * Initial release. 51 | 52 | 53 | License 54 | ------- 55 | 56 | The otx project and all original otx source files are in the public domain. 57 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Filename 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Filename

17 |

otx 18 | can use the name of the executable when creating the output file, or 19 | you may specify a name to use for all output files. You may also 20 | specify a filename extension, or let otx use the default "txt". These 21 | text fields are only starting points; they can always be overridden by 22 | the "Output:" text field in the main window.

23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Show local offsets 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Show local offsets

17 |

Displays the distance in bytes from the beginning of a function to each instruction.

18 |

19 | +196  00002c44  3c5f0002  addis    r2,r31,0x2 20 |
or
21 | 00002c44  3c5f0002  addis    r2,r31,0x2 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Show variable types 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Show variable types

17 |

Displays the data type of ObjC member variables.

18 |

19 | +100  00003564  807f0068  lwz      r3,0x68(r31)     (NSString)mOutputFileName 20 |
or
21 | +100  00003564  807f0068  lwz      r3,0x68(r31)     mOutputFileName 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/source/CLIController.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLIController.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #import "SharedDefs.h" 10 | #import "ErrorReporter.h" 11 | #import "ProgressReporter.h" 12 | 13 | // Default ProcOptions values 14 | #define SHOW_LOCAL_OFFSETS YES 15 | #define SHOW_CODE YES 16 | #define DONT_ENTAB_OUTPUT NO 17 | #define DONT_SHOW_DATA_SECTIONS NO 18 | #define SHOW_CHECKSUM YES 19 | #define SHOW_VERBOSE_MSGSENDS YES 20 | #define DONT_SEPARATE_LOGICAL_BLOCKS NO 21 | #define DEMANGLE_CPP_NAMES YES 22 | #define SHOW_METHOD_RETURN_TYPES YES 23 | #define SHOW_VARIABLE_TYPES YES 24 | #define SHOW_RETURN_STATEMENTS YES 25 | 26 | // ============================================================================ 27 | 28 | @interface CLIController : NSObject 29 | { 30 | @private 31 | NSURL* iOFile; 32 | cpu_type_t iArchSelector; 33 | uint32_t iFileArchMagic; 34 | NSString* iExeName; 35 | BOOL iVerify; 36 | BOOL iShowProgress; 37 | ProcOptions iOpts; 38 | } 39 | 40 | - (id)initWithArgs: (char**)argv 41 | count: (SInt32)argc; 42 | - (void)usage; 43 | - (void)processFile; 44 | - (void)verifyNops; 45 | - (void)newPackageFile: (NSURL*)inPackageFile; 46 | - (void)newOFile: (NSURL*)inOFile 47 | needsPath: (BOOL)inNeedsPath; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /src/source/Processors/X8664Processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | X8664Processor.h 3 | 4 | A subclass of Exe64Processor that handles x86_64-specific issues. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe64Processor.h" 12 | #import "Deobfuscator.h" 13 | 14 | #define REX_BIT_ON (1 << 3) 15 | #define REX_BIT_OFF 0 16 | 17 | /*#define REX_W(r) ((r) >> 3 & 0x1) 18 | #define REX_R(r) ((r) >> 2 & 0x1) // extends "REG1" 19 | #define REX_X(r) ((r) >> 1 & 0x1) 20 | #define REX_B(r) ((r) & 0x1) // extends "REG2"*/ 21 | 22 | #define REX_W(x) ((x) & 0x8) 23 | #define REX_R(x) ((x) & 0x4) // extends "REG1" 24 | #define REX_X(x) ((x) & 0x2) 25 | #define REX_B(x) ((x) & 0x1) // extends "REG2" 26 | 27 | #define XREG1(n, x) (REG1((n)) | (REX_R((x)) << 1)) 28 | #define XREG2(n, x) (REG2((n)) | (REX_B(x) << 3)) 29 | 30 | // Extended register identifiers in r/m field of mod r/m byte 31 | enum { 32 | R8 = 8, 33 | R9, 34 | R10, 35 | R11, 36 | R12, 37 | R13, 38 | R14, 39 | R15 40 | }; 41 | 42 | // ============================================================================ 43 | 44 | @interface X8664Processor : Exe64Processor 45 | { 46 | GP64RegisterInfo iStack[MAX_STACK_SIZE]; 47 | GP64RegisterInfo iRegInfos[16]; 48 | 49 | Var64Info* iLocalSelves; // 'self' copied to local variables 50 | uint32_t iNumLocalSelves; 51 | Var64Info* iLocalVars; 52 | uint32_t iNumLocalVars; 53 | UInt64 iHighestJumpTarget; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | otx Help 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | <body bgcolor="#e6e6e6"> 35 | <h2>This document set is best viewed in a browser that supports frames. To access the first page <a href="chapter_1_section_1.html">Click here</a></h2> 36 | </body> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | otx Help: Preferences 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | <body bgcolor="#e6e6e6"> 35 | <h2>This document set is best viewed in a browser that supports frames. To access the first page <a href="chapter_2_section_1.html">Click here</a></h2> 36 | </body> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/source/Categories/ObjcAccessors.h: -------------------------------------------------------------------------------- 1 | /* 2 | ObjcAccessors.h 3 | 4 | What the filename says. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe32Processor.h" 12 | 13 | @interface Exe32Processor(ObjcAccessors) 14 | 15 | - (BOOL)getObjcClassPtr: (objc_32_class_ptr*)outClass 16 | fromMethod: (uint32_t)inAddress; 17 | - (BOOL)getObjcClassPtr: (objc_32_class_ptr *)outClassPtr 18 | fromName: (const char*)inName; 19 | - (BOOL)getObjcMethod: (MethodInfo**)outMI 20 | fromAddress: (uint32_t)inAddress; 21 | 22 | // Obj-C 1 Only 23 | - (BOOL)getObjc1CatPtr: (objc1_32_category**)outCat 24 | fromMethod: (uint32_t)inAddress; 25 | - (BOOL)getObjc1MethodList: (objc1_32_method_list*)outList 26 | methods: (objc1_32_method**)outMethods 27 | fromAddress: (uint32_t)inAddress; 28 | - (BOOL)getObjc1Description: (char**)outDescription 29 | fromObject: (const char*)inObject 30 | type: (UInt8)inType; 31 | - (BOOL)getObjc1Symtab: (objc1_32_symtab*)outSymTab 32 | defs: (uint32_t **)outDefs 33 | fromModule: (objc1_32_module*)inModule; 34 | - (BOOL)getObjc1Class: (objc1_32_class*)outClass 35 | fromDef: (uint32_t)inDef; 36 | - (BOOL)getObjc1Category: (objc1_32_category*)outCat 37 | fromDef: (uint32_t)inDef; 38 | - (BOOL)getObjc1Class: (objc1_32_class*)outClass 39 | fromName: (const char*)inName; 40 | - (BOOL)getObjc1MetaClass: (objc1_32_class*)outClass 41 | fromClass: (objc1_32_class*)inClass; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /src/source/SystemIncludes.h: -------------------------------------------------------------------------------- 1 | /* 2 | SystemIncludes.h 3 | 4 | In order to implement the struct shortcut, all system files that define 5 | structs need to be #included before the #defines. To make this easier, 6 | all such files are included from here, and other files simply include 7 | this file. The behavior of the #import directive makes this safe. 8 | 9 | This file is in the public domain. 10 | */ 11 | 12 | #ifdef __OBJC__ 13 | #import 14 | #endif 15 | 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | 29 | #define fat_header struct fat_header 30 | #define fat_arch struct fat_arch 31 | #define mach_header struct mach_header 32 | #define mach_header_64 struct mach_header_64 33 | #define load_command struct load_command 34 | #define segment_command struct segment_command 35 | #define segment_command_64 struct segment_command_64 36 | #define symtab_command struct symtab_command 37 | #define dysymtab_command struct dysymtab_command 38 | #define nlist struct nlist 39 | #define nlist_64 struct nlist_64 40 | #define section struct section 41 | #define section_64 struct section_64 42 | 43 | // carpal tunnel inhibitors 44 | #define UTF8STRING(s) [(s) UTF8String] 45 | #define NSSTRING(s) [NSString stringWithUTF8String: (s)] 46 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/chapter_1_section_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Specifying files to analyze. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Specifying files to analyze.

17 |

There 18 | are several ways to open an executable file in otx. You can drop a file 19 | onto the main window, or onto otx's icon either in the Finder or Dock. 20 | You can also use the "Open" command in otx's File menu. If you drop an 21 | application package(.app) onto otx, it will attempt to open the 22 | application's main executable file. In some cases, the application 23 | package and executable file have different names, and you must locate 24 | the executable file manually (Show Package Contents) and open it directly. 25 | Similarly, if you want to open secondary executable files inside an 26 | application package, such as frameworks, these must be located and 27 | opened manually.

28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/English.lproj/Help/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | otx Help 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | <body bgcolor="#e6e6e6"> 35 | <h2>This document set is best viewed in a browser that supports frames. To access the first page <a href="Overview/chapter_1_section_1.html">Click here</a></h2> 36 | </body> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/index_last.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | otx Help: Open file with application 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | <body bgcolor="#e6e6e6"> 35 | <h2>This document set is best viewed in a browser that supports frames. To access the first page <a href="chapter_2_section_12.html">Click here</a></h2> 36 | </body> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/index_last.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | otx Help: Specifying files to analyze. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | <body bgcolor="#e6e6e6"> 35 | <h2>This document set is best viewed in a browser that supports frames. To access the first page <a href="chapter_1_section_2.html">Click here</a></h2> 36 | </body> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleOSTypes 11 | 12 | **** 13 | 14 | CFBundleTypeExtensions 15 | 16 | * 17 | 18 | CFBundleTypeName 19 | NSFilenamesPboardType 20 | CFBundleTypeRole 21 | Viewer 22 | LSTypeIsPackage 23 | 24 | 25 | 26 | CFBundleExecutable 27 | ${EXECUTABLE_NAME} 28 | CFBundleGetInfoString 29 | 0.17 (Public Domain, https://github.com/x43x61x69/OTX) 30 | CFBundleHelpBookFolder 31 | Help 32 | CFBundleHelpBookName 33 | otx Help 34 | CFBundleIconFile 35 | App Icon.icns 36 | CFBundleIdentifier 37 | $(PRODUCT_BUNDLE_IDENTIFIER) 38 | CFBundleInfoDictionaryVersion 39 | 6.0 40 | CFBundleName 41 | ${PRODUCT_NAME} 42 | CFBundlePackageType 43 | APPL 44 | CFBundleShortVersionString 45 | 0.17 46 | CFBundleSignature 47 | ot++ 48 | CFBundleVersion 49 | 566 50 | LSApplicationCategoryType 51 | public.app-category.developer-tools 52 | NSHumanReadableCopyright 53 | The otx project and all original otx source files are in the public domain. 54 | NSMainNibFile 55 | MainMenu 56 | NSPrincipalClass 57 | NSApplication 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/source/SmoothViewAnimation.m: -------------------------------------------------------------------------------- 1 | /* 2 | SmoothViewAnimation.m 3 | 4 | Adapted from the smooth animation example in 5 | http://developer.apple.com/documentation/Cocoa/Conceptual/AnimationGuide/AnimationGuide.pdf 6 | This version caches the window in the new init method. It also no longer 7 | tweaks the window's origin. Used only vertically, it has not been tested 8 | with horizontal resizement. 9 | 10 | This file is in the public domain. 11 | */ 12 | 13 | #import 14 | 15 | #import "SmoothViewAnimation.h" 16 | 17 | @implementation SmoothViewAnimation 18 | 19 | // initWithViewAnimations: 20 | // ---------------------------------------------------------------------------- 21 | 22 | - (id)initWithViewAnimations: (NSArray*)viewAnimations 23 | { 24 | if ((self = [super initWithViewAnimations: viewAnimations])) 25 | { 26 | // Find the first window object in the array. 27 | uint32_t numAnimations = (uint32_t)[viewAnimations count]; 28 | uint32_t i; 29 | id object; 30 | Class windowClass = [NSWindow class]; 31 | 32 | for (i = 0; i < numAnimations; i++) 33 | { 34 | object = [[viewAnimations objectAtIndex: i] 35 | objectForKey: NSViewAnimationTargetKey]; 36 | 37 | if ([object isKindOfClass: windowClass]) 38 | { 39 | iWindow = object; 40 | break; 41 | } 42 | } 43 | } 44 | 45 | return self; 46 | } 47 | 48 | // setCurrentProgress: 49 | // ---------------------------------------------------------------------------- 50 | 51 | - (void)setCurrentProgress: (NSAnimationProgress)progress 52 | { 53 | // Call super to update the progress value. 54 | [super setCurrentProgress: progress]; 55 | 56 | if (!iWindow) // can't do much without a window 57 | return; 58 | 59 | // Update the window position. As stupid as this looks, [mWindow display] 60 | // just doesn't cut it. 61 | [iWindow setFrame: [iWindow frame] display: YES animate: YES]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /src/source/Categories/Object64Loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | Object64Loader.h 3 | 4 | A category on Exe64Processor that contains all the loadXXX methods. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe64Processor.h" 12 | 13 | @interface Exe64Processor(Object64Loader) 14 | 15 | - (BOOL)loadMachHeader; 16 | - (void)loadLCommands; 17 | - (void)loadObjcClassList; 18 | - (void)loadSegment: (segment_command_64*)inSegPtr; 19 | - (void)loadSymbols: (symtab_command*)inSymPtr; 20 | - (void)loadCStringSection: (section_64*)inSect; 21 | - (void)loadNSStringSection: (section_64*)inSect; 22 | - (void)loadLit4Section: (section_64*)inSect; 23 | - (void)loadLit8Section: (section_64*)inSect; 24 | - (void)loadTextSection: (section_64*)inSect; 25 | - (void)loadCoalTextSection: (section_64*)inSect; 26 | - (void)loadCoalTextNTSection: (section_64*)inSect; 27 | - (void)loadConstTextSection: (section_64*)inSect; 28 | - (void)loadObjcMethnameSection: (section_64*)inSect; 29 | - (void)loadObjcMethtypeSection: (section_64*)inSect; 30 | - (void)loadObjcClassnameSection: (section_64*)inSect; 31 | - (void)loadDataSection: (section_64*)inSect; 32 | - (void)loadCoalDataSection: (section_64*)inSect; 33 | - (void)loadCoalDataNTSection: (section_64*)inSect; 34 | - (void)loadConstDataSection: (section_64*)inSect; 35 | - (void)loadDyldDataSection: (section_64*)inSect; 36 | - (void)loadCFStringSection: (section_64*)inSect; 37 | - (void)loadNonLazySymbolSection: (section_64*)inSect; 38 | - (void)loadImpPtrSection: (section_64*)inSect; 39 | - (void)loadObjcClassListSection: (section_64*)inSect; 40 | - (void)loadObjcCatListSection: (section_64*)inSect; 41 | - (void)loadObjcConstSection: (section_64*)inSect; 42 | - (void)loadObjcProtoListSection: (section_64*)inSect; 43 | - (void)loadObjcSuperRefsSection: (section_64*)inSect; 44 | - (void)loadObjcClassRefsSection: (section_64*)inSect; 45 | - (void)loadObjcProtoRefsSection: (section_64*)inSect; 46 | - (void)loadObjcMsgRefsSection: (section_64*)inSect; 47 | - (void)loadObjcSelRefsSection: (section_64*)inSect; 48 | - (void)loadObjcDataSection: (section_64*)inSect; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /src/source/DropBox.h: -------------------------------------------------------------------------------- 1 | /* 2 | DropBox.h 3 | 4 | A subclass of NSBox that implements drag n drop. Drag hiliting mimics 5 | NSTextField's focus border. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | // Keep these <= 255 please. 13 | #define kBorderWidth 6 14 | #define kTexturedBorderWidth 7 15 | 16 | #define kFillAlpha 0.06f 17 | 18 | // Alpha values for each one-pixel frame, from outer to inner. The 19 | // outermost frame(s) overlay NSBox's border. 20 | static const float gAlphas[4][kBorderWidth] = 21 | {{0.9f, 0.7f, 0.5f, 0.3f, 0.2f, 0.0f}, // NSNoBorder 22 | {0.4f, 0.9f, 0.6f, 0.3f, 0.2f, 0.0f}, // NSLineBorder 23 | {0.4f, 0.4f, 0.8f, 0.6f, 0.4f, 0.2f}, // NSBezelBorder 24 | {0.4f, 0.4f, 0.8f, 0.6f, 0.4f, 0.2f}}; // NSGrooveBorder 25 | 26 | // Textured windows require a bit more. 27 | static const float gTexturedAlphas[4][kTexturedBorderWidth] = 28 | {{1.0f, 0.9f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f}, // NSNoBorder 29 | {0.4f, 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f}, // NSLineBorder 30 | {0.4f, 0.4f, 1.0f, 0.8f, 0.6f, 0.4f, 0.2f}, // NSBezelBorder 31 | {0.4f, 0.4f, 1.0f, 0.8f, 0.6f, 0.4f, 0.2f}}; // NSGrooveBorder 32 | 33 | // Leopard textured windows require a bit less. 34 | static const float gLeopardTexturedAlphas[4][kTexturedBorderWidth] = 35 | {{1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f, 0.0f}, // NSNoBorder 36 | {0.4f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f, 0.0f}, // NSLineBorder 37 | {0.4f, 0.4f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f}, // NSBezelBorder 38 | {0.4f, 0.4f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f}}; // NSGrooveBorder 39 | 40 | // ============================================================================ 41 | 42 | @interface DropBox : NSBox 43 | { 44 | IBOutlet id iDelegate; 45 | 46 | BOOL iShowHilite; 47 | BOOL iFillRect; 48 | } 49 | 50 | - (void)setFillsRect: (BOOL)inFill; 51 | 52 | @end 53 | 54 | @interface NSObject(DropBoxDelegate) 55 | 56 | - (NSDragOperation)dropBox: (DropBox*)inDropBox 57 | dragDidEnter: (id )inItem; 58 | - (void)dropBox: (DropBox*)inDropBox 59 | dragDidExit: (id )inItem; 60 | - (BOOL)dropBox: (DropBox*)inDropBox 61 | didReceiveItem: (id )inItem; 62 | 63 | @end -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/toc_closed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | otx Help: TOC 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
otx Help
Preferences
73 | 74 | 75 |
76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/toc_closed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | otx Help: TOC 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
otx Help
Contents
73 | 74 | 75 |
76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/source/Categories/ObjectLoader.h: -------------------------------------------------------------------------------- 1 | /* 2 | ObjectLoader.h 3 | 4 | A category on Exe32Processor that contains all the loadXXX methods. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe32Processor.h" 12 | 13 | @interface Exe32Processor(ObjectLoader) 14 | 15 | - (BOOL)loadMachHeader; 16 | - (void)loadLCommands; 17 | - (void)loadSegment: (segment_command*)inSegPtr; 18 | - (void)loadSymbols: (symtab_command*)inSymPtr; 19 | - (void)loadObjcSection: (section*)inSect; 20 | - (void)loadObjcModules; 21 | - (void)loadObjcClassList; 22 | - (void)loadCStringSection: (section*)inSect; 23 | - (void)loadNSStringSection: (section*)inSect; 24 | - (void)loadClassSection: (section*)inSect; 25 | - (void)loadMetaClassSection: (section*)inSect; 26 | - (void)loadIVarSection: (section*)inSect; 27 | - (void)loadObjcModSection: (section*)inSect; 28 | - (void)loadObjcSymSection: (section*)inSect; 29 | - (void)loadObjcMethnameSection: (section*)inSect; 30 | - (void)loadObjcMethtypeSection: (section*)inSect; 31 | - (void)loadObjcClassnameSection: (section*)inSect; 32 | - (void)loadLit4Section: (section*)inSect; 33 | - (void)loadLit8Section: (section*)inSect; 34 | - (void)loadTextSection: (section*)inSect; 35 | - (void)loadCoalTextSection: (section*)inSect; 36 | - (void)loadCoalTextNTSection: (section*)inSect; 37 | - (void)loadConstTextSection: (section*)inSect; 38 | - (void)loadDataSection: (section*)inSect; 39 | - (void)loadCoalDataSection: (section*)inSect; 40 | - (void)loadCoalDataNTSection: (section*)inSect; 41 | - (void)loadConstDataSection: (section*)inSect; 42 | - (void)loadDyldDataSection: (section*)inSect; 43 | - (void)loadCFStringSection: (section*)inSect; 44 | - (void)loadNonLazySymbolSection: (section*)inSect; 45 | - (void)loadObjcClassListSection: (section*)inSect; 46 | - (void)loadObjcCatListSection: (section*)inSect; 47 | - (void)loadObjcConstSection: (section*)inSect; 48 | - (void)loadObjcProtoListSection: (section*)inSect; 49 | - (void)loadObjcSuperRefsSection: (section*)inSect; 50 | - (void)loadObjcClassRefsSection: (section*)inSect; 51 | - (void)loadObjcProtoRefsSection: (section*)inSect; 52 | - (void)loadObjcMsgRefsSection: (section*)inSect; 53 | - (void)loadObjcSelRefsSection: (section*)inSect; 54 | - (void)loadObjcDataSection: (section*)inSect; 55 | - (void)loadImpPtrSection: (section*)inSect; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /src/source/Categories/Searchers64.m: -------------------------------------------------------------------------------- 1 | /* 2 | Searchers64.m 3 | 4 | A category on Exe64Processor that contains the various binary search 5 | methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Searchers64.h" 13 | 14 | @implementation Exe64Processor(Searchers64) 15 | 16 | // findSymbolByAddress: 17 | // ---------------------------------------------------------------------------- 18 | 19 | - (char*)findSymbolByAddress: (uint64_t)inAddress 20 | { 21 | if (!iFuncSyms) 22 | return NO; 23 | 24 | nlist_64 searchKey = {{0}, 0, 0, 0, inAddress}; 25 | nlist_64* symbol = bsearch(&searchKey, 26 | iFuncSyms, iNumFuncSyms, sizeof(nlist_64), 27 | (COMPARISON_FUNC_TYPE)Sym_Compare_64); 28 | 29 | if (symbol) 30 | return (char*)((char *)iMachHeaderPtr + iStringTableOffset + symbol->n_un.n_strx); 31 | else 32 | return NULL; 33 | } 34 | 35 | // findClassMethod:byAddress: 36 | // ---------------------------------------------------------------------------- 37 | 38 | - (BOOL)findClassMethod: (Method64Info**)outMI 39 | byAddress: (UInt64)inAddress; 40 | { 41 | if (!outMI) 42 | return NO; 43 | 44 | if (!iClassMethodInfos) 45 | { 46 | *outMI = NULL; 47 | return NO; 48 | } 49 | 50 | Method64Info searchKey = {{0, 0, inAddress}, {0}, NO}; 51 | 52 | *outMI = bsearch(&searchKey, 53 | iClassMethodInfos, iNumClassMethodInfos, sizeof(Method64Info), 54 | (COMPARISON_FUNC_TYPE) 55 | (iSwapped ? Method64Info_Compare_Swapped : Method64Info_Compare)); 56 | 57 | return (*outMI != NULL); 58 | } 59 | 60 | // findIvar:inClass:withOffset: 61 | // ---------------------------------------------------------------------------- 62 | // TODO: keep a sorted list of ClassInfo's, where each ClassInfo keeps a sorted 63 | // list of objc2_ivar_t's. 64 | 65 | - (BOOL)findIvar: (objc2_64_ivar_t**)outIvar 66 | inClass: (objc2_64_class_t*)inClass 67 | withOffset: (UInt64)inOffset 68 | { 69 | if (!inClass || !outIvar) 70 | return NO; 71 | 72 | objc2_64_ivar_t searchKey = {inOffset, 0, 0, 0, 0}; 73 | 74 | *outIvar = bsearch(&searchKey, iClassIvars, iNumClassIvars, sizeof(objc2_64_ivar_t), 75 | (COMPARISON_FUNC_TYPE)objc2_64_ivar_t_Compare); 76 | 77 | return (*outIvar != NULL); 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /src/source/Processors/X86Processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | X86Processor.h 3 | 4 | A subclass of Exe32Processor that handles x86-specific issues. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe32Processor.h" 12 | #import "Deobfuscator.h" 13 | 14 | // Addressing modes in mod field of mod r/m byte. 15 | // See table 2.2 in the Pentium manual. 16 | #define MODimm 0 // [reg] 17 | #define MOD8 1 // [reg] + disp8 18 | #define MOD32 2 // [reg] + disp32 19 | #define MODx 3 // ignored 20 | 21 | // Addressing modes in r/m field of mod r/m byte. 22 | // See table 2.2 in the Pentium manual. 23 | #define DISP32 5 // disp32 when mod == 0 24 | 25 | // Register identifiers in r/m field of mod r/m byte 26 | enum { 27 | NO_REG = -1, 28 | EAX, // 0 29 | ECX, // 1 30 | EDX, // 2 31 | EBX, // 3 32 | ESP, // 4 33 | EBP, // 5 34 | ESI, // 6 35 | EDI // 7 36 | }; 37 | 38 | // Macros for various x86 data 39 | #define LO(x) ((x) & 0xf) // bits 0-3 40 | #define HI(x) (((x) >> 4) & 0xf) // bits 4-7 41 | //#define DIR(x) (((x) >> 1) & 0x1) // bit 1 42 | #define MOD(x) (((x) >> 6) & 0x3) // bits 6-7 43 | #define REG1(x) (((x) >> 3) & 0x7) // bits 3-5 44 | #define REG2(x) ((x) & 0x7) // bits 0-2 45 | #define OPEXT(x) REG1((x)) 46 | #define RM(x) REG2((x)) 47 | #define HAS_SIB(x) (MOD((x)) != MODx && REG2((x)) == ESP) 48 | #define HAS_DISP8(x) (MOD((x)) == MOD8) 49 | #define HAS_REL_DISP32(x) (MOD((x)) == MOD32) 50 | #define HAS_ABS_DISP32(x) (MOD((x)) == MODimm && REG2((x)) == EBP) 51 | 52 | #define IS_JUMP(o, so) \ 53 | ((o) == 0xe3 || (o) == 0xe9 || (o) == 0xeb || (o) == 0xc3 || \ 54 | ((o) >= 0x71 && (o) <= 0x7f) || \ 55 | ((o) == 0x0f && (so) >= 0x81 && (so) <= 0x8f)) 56 | #define IS_CALL(o) ((o) == 0xe8) 57 | #define IS_RET(o) ((o) == 0xc3) 58 | 59 | // ============================================================================ 60 | 61 | @interface X86Processor : Exe32Processor 62 | { 63 | GPRegisterInfo iStack[MAX_STACK_SIZE]; 64 | GPRegisterInfo iRegInfos[8]; 65 | 66 | VarInfo* iLocalSelves; // 'self' copied to local variables 67 | uint32_t iNumLocalSelves; 68 | VarInfo* iLocalVars; 69 | uint32_t iNumLocalVars; 70 | } 71 | 72 | - (void) printCurrentState: (uint32_t)currentAddress; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/chapter_1_section_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | otx Help 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

otx 16 | Help

17 |

otx 18 | stands for "object tool extended". otx uses otool(object tool) to 19 | disassemble a Mach-O executable file, then enhances the disassembled 20 | output. Simple enhancements include adding the machine code of each 21 | instruction as well as the offset of each instruction from the 22 | beginning of a function. More complicated enhancements include 23 | displaying the names of ObjC methods even if symbols have been 24 | stripped, and adding comments that describe member variables, function 25 | calls, static data and more.

26 | 27 |

28 | 29 |

otx can open almost 30 | any Mach-O executable file you're likely to use- PPC or x86, single 31 | architecture or universal binary. When you open a universal binary, the 32 | popup menu show above allows you to select which architecture to 33 | disassemble. If you have lipo installed, you can easily separate the 34 | selected architecture using the "Thin" button.

35 | 36 |

If you have obfuscated 37 | your code, you may find that otool's disassembly is less than desirable. 38 | To assist you, otx includes a very basic deobfuscator. By using the 39 | "Verify" button shown above, you can verify that otool will be able to 40 | correctly disassemble your executable. If this verification fails, otx 41 | will ask if you would like to save a deobfuscated copy of your executable. 42 | Should you choose to do so, the deobfuscated copy will be automatically 43 | opened for further processing. Currently, deobfuscation is only necessary 44 | for x86 executables.

45 | 46 |

Refer to these sections:

47 | 48 |
49 | 50 | Specifying files to analyze. 51 | 52 |
53 | 54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/source/Categories/ArchSpecifics.m: -------------------------------------------------------------------------------- 1 | /* 2 | ArchSpecifics.m 3 | 4 | A category on Exe32Processor that contains most of the 5 | architecture-specific methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "ArchSpecifics.h" 13 | 14 | @implementation Exe32Processor(ArchSpecifics) 15 | 16 | // gatherFuncInfos 17 | // ---------------------------------------------------------------------------- 18 | 19 | - (void)gatherFuncInfos 20 | {} 21 | 22 | // postProcessCodeLine: 23 | // ---------------------------------------------------------------------------- 24 | 25 | - (void)postProcessCodeLine: (Line**)ioLine 26 | {} 27 | 28 | // lineIsFunction: 29 | // ---------------------------------------------------------------------------- 30 | 31 | - (BOOL)lineIsFunction: (Line*)inLine 32 | { 33 | return NO; 34 | } 35 | 36 | // codeIsBlockJump: 37 | // ---------------------------------------------------------------------------- 38 | 39 | - (BOOL)codeIsBlockJump: (UInt8*)inCode 40 | { 41 | return NO; 42 | } 43 | 44 | // codeFromLine: 45 | // ---------------------------------------------------------------------------- 46 | 47 | - (void)codeFromLine: (Line*)inLine 48 | {} 49 | 50 | // checkThunk: 51 | // ---------------------------------------------------------------------------- 52 | 53 | - (void)checkThunk:(Line*)inLine 54 | {} 55 | 56 | // getThunkInfo:forLine: 57 | // ---------------------------------------------------------------------------- 58 | 59 | - (BOOL)getThunkInfo: (ThunkInfo*)outInfo 60 | forLine: (Line*)inLine 61 | { 62 | return NO; 63 | } 64 | 65 | #pragma mark - 66 | // commentForLine: 67 | // ---------------------------------------------------------------------------- 68 | 69 | - (void)commentForLine: (Line*)inLine 70 | {} 71 | 72 | // commentForSystemCall 73 | // ---------------------------------------------------------------------------- 74 | 75 | - (void)commentForSystemCall 76 | {} 77 | 78 | // commentForMsgSend:fromLine: 79 | // ---------------------------------------------------------------------------- 80 | 81 | - (void)commentForMsgSend: (char*)ioComment 82 | fromLine: (Line*)inLine 83 | {} 84 | 85 | #pragma mark - 86 | // resetRegisters: 87 | // ---------------------------------------------------------------------------- 88 | 89 | - (void)resetRegisters: (Line*)inLine 90 | {} 91 | 92 | // updateRegisters: 93 | // ---------------------------------------------------------------------------- 94 | 95 | - (void)updateRegisters: (Line*)inLine 96 | {} 97 | 98 | // restoreRegisters: 99 | // ---------------------------------------------------------------------------- 100 | 101 | - (BOOL)restoreRegisters: (Line*)ioLine 102 | { 103 | return NO; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /src/source/Categories/Arch64Specifics.m: -------------------------------------------------------------------------------- 1 | /* 2 | Arch64Specifics.m 3 | 4 | A category on Exe64Processor that contains most of the 5 | architecture-specific methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Arch64Specifics.h" 13 | 14 | @implementation Exe64Processor(Arch64Specifics) 15 | 16 | // gatherFuncInfos 17 | // ---------------------------------------------------------------------------- 18 | 19 | - (void)gatherFuncInfos 20 | {} 21 | 22 | // postProcessCodeLine: 23 | // ---------------------------------------------------------------------------- 24 | 25 | - (void)postProcessCodeLine: (Line64**)ioLine 26 | {} 27 | 28 | // lineIsFunction: 29 | // ---------------------------------------------------------------------------- 30 | 31 | - (BOOL)lineIsFunction: (Line64*)inLine 32 | { 33 | return NO; 34 | } 35 | 36 | // codeIsBlockJump: 37 | // ---------------------------------------------------------------------------- 38 | 39 | - (BOOL)codeIsBlockJump: (UInt8*)inCode 40 | { 41 | return NO; 42 | } 43 | 44 | // codeFromLine: 45 | // ---------------------------------------------------------------------------- 46 | 47 | - (void)codeFromLine: (Line64*)inLine 48 | {} 49 | 50 | // checkThunk: 51 | // ---------------------------------------------------------------------------- 52 | 53 | - (void)checkThunk:(Line64*)inLine 54 | {} 55 | 56 | // getThunkInfo:forLine: 57 | // ---------------------------------------------------------------------------- 58 | 59 | - (BOOL)getThunkInfo: (ThunkInfo*)outInfo 60 | forLine: (Line64*)inLine 61 | { 62 | return NO; 63 | } 64 | 65 | #pragma mark - 66 | // commentForLine: 67 | // ---------------------------------------------------------------------------- 68 | 69 | - (void)commentForLine: (Line64*)inLine 70 | {} 71 | 72 | // commentForSystemCall 73 | // ---------------------------------------------------------------------------- 74 | 75 | - (void)commentForSystemCall 76 | {} 77 | 78 | // commentForMsgSend:fromLine: 79 | // ---------------------------------------------------------------------------- 80 | 81 | - (void)commentForMsgSend: (char*)ioComment 82 | fromLine: (Line64*)inLine 83 | {} 84 | 85 | #pragma mark - 86 | // resetRegisters: 87 | // ---------------------------------------------------------------------------- 88 | 89 | - (void)resetRegisters: (Line64*)inLine 90 | {} 91 | 92 | // updateRegisters: 93 | // ---------------------------------------------------------------------------- 94 | 95 | - (void)updateRegisters: (Line64*)inLine 96 | {} 97 | 98 | // restoreRegisters: 99 | // ---------------------------------------------------------------------------- 100 | 101 | - (BOOL)restoreRegisters: (Line64*)ioLine 102 | { 103 | return NO; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Overview/toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | otx Help: TOC 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
otx Help
 Specifying files to analyze
Preferences
81 | 82 | 83 |
84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/source/Categories/SysUtils.m: -------------------------------------------------------------------------------- 1 | /* 2 | SysUtils.m 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | #import 9 | 10 | #import "SystemIncludes.h" // for UTF8STRING() 11 | #import "SysUtils.h" 12 | 13 | @implementation NSObject(SysUtils) 14 | 15 | // checkOtool: 16 | // ---------------------------------------------------------------------------- 17 | 18 | - (BOOL)checkOtool: (NSString*)filePath 19 | { 20 | NSString* otoolPath = [self pathForTool: @"otool"]; 21 | NSTask* otoolTask = [[[NSTask alloc] init] autorelease]; 22 | NSPipe* silence = [NSPipe pipe]; 23 | 24 | [otoolTask setLaunchPath: otoolPath]; 25 | [otoolTask setStandardInput: [NSPipe pipe]]; 26 | [otoolTask setStandardOutput: silence]; 27 | [otoolTask setStandardError: silence]; 28 | [otoolTask launch]; 29 | [otoolTask waitUntilExit]; 30 | 31 | return ([otoolTask terminationStatus] == 1); 32 | } 33 | 34 | // pathForTool: 35 | // ---------------------------------------------------------------------------- 36 | 37 | - (NSString*)pathForTool: (NSString*)toolName 38 | { 39 | // Xcode 5+: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/otool 40 | 41 | NSString* relToolBase = [NSString pathWithComponents: 42 | [NSArray arrayWithObjects: @"/", @"usr", @"bin", nil]]; 43 | NSString* relToolPath = [relToolBase stringByAppendingPathComponent: toolName]; 44 | 45 | NSString* selectToolPath = [relToolBase stringByAppendingPathComponent: @"xcode-select"]; 46 | NSTask* selectTask = [[[NSTask alloc] init] autorelease]; 47 | NSPipe* selectPipe = [NSPipe pipe]; 48 | NSArray* args = [NSArray arrayWithObject: @"--print-path"]; 49 | 50 | [selectTask setLaunchPath: selectToolPath]; 51 | [selectTask setArguments: args]; 52 | [selectTask setStandardInput: [NSPipe pipe]]; 53 | [selectTask setStandardOutput: selectPipe]; 54 | [selectTask launch]; 55 | [selectTask waitUntilExit]; 56 | 57 | int selectStatus = [selectTask terminationStatus]; 58 | 59 | if (selectStatus == -1) 60 | return relToolPath; 61 | 62 | NSData* selectData = [[selectPipe fileHandleForReading] availableData]; 63 | NSString* absToolPath = [[[NSString alloc] initWithBytes: [selectData bytes] 64 | length: [selectData length] 65 | encoding: NSUTF8StringEncoding] autorelease]; 66 | 67 | absToolPath = [[[[absToolPath stringByTrimmingCharactersInSet: 68 | [NSCharacterSet whitespaceAndNewlineCharacterSet]] 69 | stringByAppendingPathComponent: @"Toolchains"] 70 | stringByAppendingPathComponent: @"XcodeDefault.xctoolchain"] 71 | stringByAppendingPathComponent: relToolPath]; 72 | 73 | if (![[NSFileManager defaultManager] fileExistsAtPath:absToolPath]) { 74 | return relToolPath; 75 | } 76 | 77 | return absToolPath; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /src/source/StolenDefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | StolenDefs.h 3 | 4 | Definitions stolen from, or inspired by, Darwin & cctools. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #define rotr(x, n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) 10 | #define rotl(x, n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) 11 | #define rotr64(x, n) (((x) >> ((int)(n))) | ((x) << (64 - (int)(n)))) 12 | #define rotl64(x, n) (((x) << ((int)(n))) | ((x) >> (64 - (int)(n)))) 13 | 14 | /* section_info 15 | */ 16 | typedef struct 17 | { 18 | section s; 19 | char* contents; 20 | uint32_t size; 21 | } 22 | section_info; 23 | 24 | typedef struct 25 | { 26 | section_64 s; 27 | char* contents; 28 | uint64_t size; 29 | } 30 | section_info_64; 31 | 32 | /* dyld_data_section 33 | 34 | Adapted from 35 | http://www.opensource.apple.com/darwinsource/10.4.7.ppc/cctools-590.23.6/libdyld/debug.h 36 | */ 37 | typedef struct 38 | { 39 | void* stub_binding_helper_interface; 40 | void* _dyld_func_lookup; 41 | void* start_debug_thread; 42 | mach_port_t debug_port; 43 | thread_port_t debug_thread; 44 | void* dyld_stub_binding_helper; 45 | // unsigned long core_debug; // wrong size and ignored by us anyway 46 | } 47 | dyld_data_section; 48 | 49 | 50 | 51 | /* NSString 52 | 53 | From cctools-590/otool/print_objc.c, alternate definition in 54 | http://www.opensource.apple.com/darwinsource/10.4.7.ppc/objc4-267.1/runtime/objc-private.h 55 | */ 56 | typedef struct { 57 | uint32_t isa; /* objc_class * */ 58 | uint32_t chars; /* char * */ 59 | uint32_t length; /* unsigned int */ 60 | } nxstring_object; 61 | 62 | typedef struct { 63 | uint64_t isa; /* objc_class * */ 64 | uint64_t chars; /* char * */ 65 | uint32_t length; /* unsigned int */ 66 | } nxstring_object_64; 67 | 68 | 69 | /* CFString 70 | 71 | The only piece of reverse-engineered data in otx. I was unable to find any 72 | documentation about the structure of CFStrings, but they appear to be 73 | NSStrings with an extra data member prepended. Following NSString's lead, 74 | i'm calling it 'isa'. The observed values of 'isa' change from app to app, 75 | but remain constant in each app. A little gdb effort could probably shed 76 | some light on what they actually point to, but otx has nothing to gain from 77 | that knowledge. Still, any feedback regarding this issue is most welcome. 78 | */ 79 | typedef struct { 80 | uint32_t isa; 81 | nxstring_object oc_string; 82 | } cfstring_object; 83 | 84 | typedef struct { 85 | uint64_t isa; 86 | nxstring_object_64 oc_string; 87 | } cfstring_object_64; 88 | 89 | 90 | 91 | 92 | /* The isa field of an NSString is 0x7c8 (1992) when it exists in the 93 | (__DATA,__const) section. This makes it possible to identify both 94 | NSString's and CFString's. I can't find any documentation about the 95 | 1992 date, but it is assumed to be the date of birth of NSStrings. 96 | */ 97 | #define typeid_NSString 0x000007c8 98 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/chapter_2_section_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | otx Help: Preferences 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Preferences

17 | 18 |

Refer to these sections:

19 | 20 |
21 | 22 | Show local offsets 23 | 24 |
25 | 26 | Show data sections 27 | 28 |
29 | 30 | Entab output 31 | 32 |
33 | 34 | Show md5 checksum 35 | 36 |
37 | 38 | Demangle names 39 | 40 |
41 | 42 | Show method types 43 | 44 |
45 | 46 | Show variable types 47 | 48 |
49 | 50 | Filename 51 | 52 |
53 | 54 | Location 55 |
56 | 57 | Open file with application 58 |
59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/source/DropBox.m: -------------------------------------------------------------------------------- 1 | /* 2 | DropBox.m 3 | 4 | A subclass of NSBox that implements drag n drop. Drag hiliting mimics 5 | NSTextField's focus border. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "DropBox.h" 13 | 14 | @implementation DropBox 15 | 16 | // awakeFromNib 17 | // ---------------------------------------------------------------------------- 18 | 19 | - (void)awakeFromNib 20 | { 21 | [self registerForDraggedTypes: 22 | [NSArray arrayWithObject: NSFilenamesPboardType]]; 23 | } 24 | 25 | // setFillsRect: 26 | // ---------------------------------------------------------------------------- 27 | // Call setFillsRect: YES to draw the entire frame hilited with kFillAlpha. 28 | 29 | - (void)setFillsRect: (BOOL)inFill 30 | { 31 | iFillRect = inFill; 32 | } 33 | 34 | // draggingEntered: 35 | // ---------------------------------------------------------------------------- 36 | 37 | - (NSDragOperation)draggingEntered: (id)sender 38 | { 39 | NSDragOperation dragOp = NSDragOperationNone; 40 | 41 | if (iDelegate && [iDelegate respondsToSelector: 42 | @selector(dropBox:dragDidEnter:)]) 43 | dragOp = [iDelegate dropBox: self dragDidEnter: sender]; 44 | 45 | if (dragOp == NSDragOperationNone) 46 | return dragOp; 47 | 48 | iShowHilite = YES; 49 | [self setNeedsDisplay: YES]; 50 | 51 | return dragOp; 52 | } 53 | 54 | // draggingExited: 55 | // ---------------------------------------------------------------------------- 56 | 57 | - (void)draggingExited: (id)sender 58 | { 59 | iShowHilite = NO; 60 | [self setNeedsDisplay: YES]; 61 | 62 | if (iDelegate && [iDelegate respondsToSelector: 63 | @selector(dropBox:dragDidExit:)]) 64 | [iDelegate dropBox: self dragDidExit: sender]; 65 | } 66 | 67 | // performDragOperation: 68 | // ---------------------------------------------------------------------------- 69 | 70 | - (BOOL)performDragOperation: (id)sender 71 | { 72 | iShowHilite = NO; 73 | [self setNeedsDisplay: YES]; 74 | 75 | if (!iDelegate) 76 | return NO; 77 | 78 | if ([iDelegate respondsToSelector: @selector(dropBox:didReceiveItem:)]) 79 | return [iDelegate dropBox: self didReceiveItem: sender]; 80 | 81 | return NO; 82 | } 83 | 84 | // drawRect: 85 | // ---------------------------------------------------------------------------- 86 | 87 | - (void)drawRect: (NSRect)rect 88 | { 89 | [super drawRect: rect]; 90 | 91 | if (!iShowHilite) 92 | return; 93 | 94 | NSBorderType borderType = [self borderType]; 95 | 96 | if (borderType > 3) 97 | { 98 | fprintf(stderr, "DropBox: invalid NSBorderType: %lu\n", borderType); 99 | return; 100 | } 101 | 102 | NSWindow* window = [self window]; 103 | UInt8 borderWidth; 104 | BOOL isTextured; 105 | 106 | if (window && ([window styleMask] & NSTexturedBackgroundWindowMask)) 107 | { 108 | isTextured = YES; 109 | borderWidth = kTexturedBorderWidth; 110 | } 111 | else 112 | { 113 | isTextured = NO; 114 | borderWidth = kBorderWidth; 115 | } 116 | 117 | NSRect innerRect = rect; 118 | NSColor* baseColor = [NSColor keyboardFocusIndicatorColor]; 119 | NSColor* color; 120 | UInt8 i; 121 | 122 | for (i = 0; i < borderWidth; i++) 123 | { 124 | color = [baseColor colorWithAlphaComponent: (isTextured) ? 125 | ((OS_IS_POST_TIGER) ? gLeopardTexturedAlphas[borderType][i] : 126 | gTexturedAlphas[borderType][i]) : gAlphas[borderType][i]]; 127 | [color set]; 128 | NSFrameRectWithWidthUsingOperation( 129 | innerRect, 1.0f, NSCompositeSourceOver); 130 | innerRect = NSInsetRect(innerRect, 1.0f, 1.0f); 131 | } 132 | 133 | if (iFillRect) 134 | { 135 | if (borderType == NSNoBorder || borderType == NSLineBorder) 136 | innerRect = NSInsetRect(innerRect, -1.0f, -1.0f); 137 | 138 | color = [baseColor colorWithAlphaComponent: kFillAlpha]; 139 | [color set]; 140 | NSRectFillUsingOperation(innerRect, NSCompositeSourceOver); 141 | } 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /src/source/Processors/PPCProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | PPCProcessor.h 3 | 4 | A subclass of ExeProcessor that handles PPC-specific issues. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Exe32Processor.h" 12 | 13 | // from cctools-590/otool/ppc-disasm.c 14 | // The various macros defined in that file get their names from the field 15 | // naming conventions given in the PowerPC Programming Environments Manual 16 | // available at http://www.freescale.com 17 | #define RT(x) (((x) >> 21) & 0x1f) // bits 21 - 25 18 | #define RA(x) (((x) >> 16) & 0x1f) // bits 16 - 20 19 | #define RB(x) (((x) >> 11) & 0x1f) // bits 11 - 15 20 | #define MB(x) (((x) >> 6) & 0x1f) // bits 6 - 10 21 | #define ME(x) (((x) >> 1) & 0x1f) // bits 1 - 5 22 | #define SV(x) ((x) & 0x1f) // bits 0 - 4 "Shift Value" 23 | #define SB(x) ((x) & 0x20) // bit 5 "Shift Bit" 24 | #define BO(x) RT((x)) 25 | #define RS(x) RT((x)) 26 | 27 | // otool masks the entire instruction with 0xfc000000, rather than accessing 28 | // the primary opcode field directly. Maybe this is to help each case in a 29 | // switch statement stand out, maybe it's faster, who knows... I define a 30 | // PO macro here, and use the values given in the PEM. The SO macro accesses 31 | // the unnamed 10-bit field that specifies secondary opcodes in an instruction 32 | // of the XO(extended operand) form. The SPR macro accesses the "special 33 | // register" field of mfspr and mtspr instructions(LR, CTR). SIMM and UIMM 34 | // access the signed and unsigned immediate values. 35 | #define PO(x) (((x) >> 26) & 0x3f) // bits 26 - 31 36 | #define SO(x) (((x) >> 1) & 0x3ff) // bits 1 - 10 37 | #define SPR(x) ((((x) >> 6) & 0x3e0) | (((x) >> 16) & 0x1f)) 38 | #define UIMM(x) ((x) & 0xffff) // bits 0 - 15 39 | #define SIMM(x) (SInt16)((x) & 0xffff) // bits 0 - 15 40 | #define AA(x) (((x) >> 1) & 0x1) // bit 1 41 | #define LK(x) ((x) & 0x1) // bit 0 42 | #define BD(x) (SInt16)((x) & 0xfffc) // bits 2 - 15 43 | 44 | // bits 2 - 25, sign extended 45 | #define LI(x) (SInt32) \ 46 | (((x) & 0x02000000) ? \ 47 | ((x) & 0x03fffffc) | 0xfc000000 : \ 48 | ((x) & 0x03fffffc)) 49 | 50 | // SPR values 51 | #define LR 8 52 | #define CTR 9 53 | 54 | // indices into MachineState.regInfos array 55 | #define LRIndex 32 56 | #define CTRIndex 33 57 | 58 | #define IS_BLOCK_BRANCH(i) \ 59 | ((PO(i) == 0x10 || PO(i) == 0x12 || PO(i) == 0x13) && \ 60 | (!AA(i) && !LK(i))) 61 | 62 | #define IS_BRANCH_LINK(i) \ 63 | ((PO(i) == 0x10 && LK(i)) || \ 64 | (PO(i) == 0x12 && LK(i)) || \ 65 | (PO(i) == 0x13 && (i & 0x7ff) == 0x421)) 66 | 67 | #define IS_BRANCH_CONDITIONAL(i) \ 68 | (((PO((i)) == 0x13 && SO((i)) == 0x10) || (PO((i)) == 0x10)) \ 69 | && (BO((i)) != 0x14)) 70 | 71 | #define IS_BLR(i) ((i) == 0x4e800020) 72 | 73 | // Addresses and names of functions in the ObjC runtime page, stolen from 74 | // http://www.opensource.apple.com/darwinsource/10.4.7.ppc/objc4-267.1/runtime/objc-rtp.h 75 | 76 | #define kRTAddress_objc_msgSend 0xfffeff00 77 | #define kRTAddress_objc_assign_ivar 0xfffefec0 78 | #define kRTAddress_objc_assign_global 0xfffefeb0 79 | #define kRTAddress_objc_assign_strongCast 0xfffefea0 80 | 81 | #define kRTName_objc_msgSend "_objc_msgSend_rtp" 82 | #define kRTName_objc_assign_ivar "_objc_assign_ivar_rtp" 83 | #define kRTName_objc_assign_global "_objc_assign_global_rtp" 84 | #define kRTName_objc_assign_strongCast "_objc_assign_strongCast_rtp" 85 | 86 | // Addresses and names of some dyld routines, stolen from 87 | // http://www.opensource.apple.com/darwinsource/10.4.7.ppc/Csu-58/dyld.s 88 | 89 | #define kDyldAddress_LaSymBindingEntry 0x8fe01000 90 | #define kDyldAddress_FuncLookupPointer 0x8fe01008 91 | 92 | #define kDyldName_LaSymBindingEntry "dyld_lazy_symbol_binding_entry_point" 93 | #define kDyldName_FuncLookupPointer "dyld_func_lookup_pointer" 94 | 95 | // ============================================================================ 96 | 97 | @interface PPCProcessor : Exe32Processor 98 | { 99 | GPRegisterInfo iRegInfos[32]; 100 | GPRegisterInfo iLR; 101 | GPRegisterInfo iCTR; 102 | 103 | VarInfo* iLocalSelves; // 'self' copied to local variables 104 | uint32_t iNumLocalSelves; 105 | VarInfo* iLocalVars; 106 | uint32_t iNumLocalVars; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /src/source/Categories/ListUtils.m: -------------------------------------------------------------------------------- 1 | /* 2 | ListUtils.m 3 | 4 | A category on Exe32Processor for linked list manipulation. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "ListUtils.h" 12 | 13 | @implementation Exe32Processor(ListUtils) 14 | 15 | // Each text line is stored in an element of a doubly-linked list. These are 16 | // vanilla textbook funcs for maintaining the list. 17 | 18 | // insertLine:before:inList: 19 | // ---------------------------------------------------------------------------- 20 | 21 | - (void)insertLine: (Line*)inLine 22 | before: (Line*)nextLine 23 | inList: (Line**)listHead 24 | { 25 | if (!nextLine) 26 | return; 27 | 28 | if (nextLine == *listHead) 29 | *listHead = inLine; 30 | 31 | inLine->prev = nextLine->prev; 32 | inLine->next = nextLine; 33 | nextLine->prev = inLine; 34 | 35 | if (inLine->prev) 36 | inLine->prev->next = inLine; 37 | } 38 | 39 | // insertLine:after:inList: 40 | // ---------------------------------------------------------------------------- 41 | 42 | - (void)insertLine: (Line*)inLine 43 | after: (Line*)prevLine 44 | inList: (Line**)listHead 45 | { 46 | if (!prevLine) 47 | { 48 | *listHead = inLine; 49 | return; 50 | } 51 | 52 | inLine->next = prevLine->next; 53 | inLine->prev = prevLine; 54 | prevLine->next = inLine; 55 | 56 | if (inLine->next) 57 | inLine->next->prev = inLine; 58 | } 59 | 60 | // replaceLine:withLine:inList: 61 | // ---------------------------------------------------------------------------- 62 | // This non-standard method is used for merging the verbose and plain lists. 63 | 64 | - (void)replaceLine: (Line*)inLine 65 | withLine: (Line*)newLine 66 | inList: (Line**)listHead 67 | { 68 | if (!inLine || !newLine) 69 | return; 70 | 71 | if (inLine == *listHead) 72 | *listHead = newLine; 73 | 74 | newLine->next = inLine->next; 75 | newLine->prev = inLine->prev; 76 | 77 | if (newLine->next) 78 | newLine->next->prev = newLine; 79 | 80 | if (newLine->prev) 81 | newLine->prev->next = newLine; 82 | 83 | if (inLine->chars) 84 | free(inLine->chars); 85 | 86 | free(inLine); 87 | } 88 | 89 | // printLinesFromList: 90 | // ---------------------------------------------------------------------------- 91 | // Print our modified lines to a FILE*. The FILE* is a real file in the GUI 92 | // target, and stdout in the CLI target. 93 | 94 | - (BOOL)printLinesFromList: (Line*)listHead 95 | { 96 | FILE* outFile = NULL; 97 | 98 | // In the CLI target, mOutputFilePath is nil. 99 | if (iOutputFilePath) 100 | { 101 | const char* outPath = UTF8STRING(iOutputFilePath); 102 | outFile = fopen(outPath, "w"); 103 | } 104 | else 105 | outFile = stdout; 106 | 107 | if (!outFile) 108 | { 109 | perror("otx: unable to open output file"); 110 | return NO; 111 | } 112 | 113 | Line* theLine = listHead; 114 | 115 | // Cache the fileno and use SYS_write for maximum speed. 116 | SInt32 fileNum = fileno(outFile); 117 | 118 | while (theLine) 119 | { 120 | if (syscall(SYS_write, fileNum, theLine->chars, theLine->length) == -1) 121 | { 122 | perror("otx: unable to write to output file"); 123 | 124 | if (iOutputFilePath) 125 | { 126 | if (fclose(outFile) != 0) 127 | perror("otx: unable to close output file"); 128 | } 129 | 130 | return NO; 131 | } 132 | 133 | theLine = theLine->next; 134 | } 135 | 136 | if (iOutputFilePath) 137 | { 138 | if (fclose(outFile) != 0) 139 | { 140 | perror("otx: unable to close output file"); 141 | return NO; 142 | } 143 | } 144 | 145 | return YES; 146 | } 147 | 148 | // deleteLinesFromList: 149 | // ---------------------------------------------------------------------------- 150 | 151 | - (void)deleteLinesFromList: (Line*)listHead 152 | { 153 | Line* theLine = listHead; 154 | 155 | while (theLine) 156 | { 157 | if (theLine->prev) // If there's one behind us... 158 | { 159 | free(theLine->prev->chars); // delete it. 160 | free(theLine->prev); 161 | } 162 | 163 | if (theLine->next) // If there are more... 164 | theLine = theLine->next; // jump to next one and continue. 165 | else 166 | { // This is the last one, delete it. 167 | free(theLine->chars); 168 | free(theLine); 169 | theLine = NULL; 170 | } 171 | } 172 | } 173 | 174 | // deleteLinesBefore:fromList: 175 | // ---------------------------------------------------------------------------- 176 | 177 | - (void)deleteLinesBefore: (Line*)inLine 178 | fromList: (Line**)listHead 179 | { 180 | Line* theLine = *listHead; 181 | 182 | while (theLine) 183 | { 184 | if (theLine->prev) // If there's one behind us... 185 | { 186 | free(theLine->prev->chars); // delete it. 187 | free(theLine->prev); 188 | } 189 | 190 | if (theLine->next && theLine->next != inLine) // If there are more... 191 | theLine = theLine->next; // jump to next one and continue. 192 | else 193 | { // This is the last one, delete it. 194 | free(theLine->chars); 195 | free(theLine); 196 | theLine = NULL; 197 | } 198 | } 199 | 200 | // Update the head. 201 | *listHead = inLine; 202 | (*listHead)->prev = NULL; 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /src/source/Categories/List64Utils.m: -------------------------------------------------------------------------------- 1 | /* 2 | List64Utils.m 3 | 4 | A category on Exe64Processor that contains the linked list 5 | manipulation methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "List64Utils.h" 13 | 14 | @implementation Exe64Processor(List64Utils) 15 | 16 | // Each text line is stored in an element of a doubly-linked list. These are 17 | // vanilla textbook funcs for maintaining the list. 18 | 19 | // insertLine:before:inList: 20 | // ---------------------------------------------------------------------------- 21 | 22 | - (void)insertLine: (Line64*)inLine 23 | before: (Line64*)nextLine 24 | inList: (Line64**)listHead 25 | { 26 | if (!nextLine) 27 | return; 28 | 29 | if (nextLine == *listHead) 30 | *listHead = inLine; 31 | 32 | inLine->prev = nextLine->prev; 33 | inLine->next = nextLine; 34 | nextLine->prev = inLine; 35 | 36 | if (inLine->prev) 37 | inLine->prev->next = inLine; 38 | } 39 | 40 | // insertLine:after:inList: 41 | // ---------------------------------------------------------------------------- 42 | 43 | - (void)insertLine: (Line64*)inLine 44 | after: (Line64*)prevLine 45 | inList: (Line64**)listHead 46 | { 47 | if (!prevLine) 48 | { 49 | *listHead = inLine; 50 | return; 51 | } 52 | 53 | inLine->next = prevLine->next; 54 | inLine->prev = prevLine; 55 | prevLine->next = inLine; 56 | 57 | if (inLine->next) 58 | inLine->next->prev = inLine; 59 | } 60 | 61 | // replaceLine:withLine:inList: 62 | // ---------------------------------------------------------------------------- 63 | // This non-standard method is used for merging the verbose and plain lists. 64 | 65 | - (void)replaceLine: (Line64*)inLine 66 | withLine: (Line64*)newLine 67 | inList: (Line64**)listHead 68 | { 69 | if (!inLine || !newLine) 70 | return; 71 | 72 | if (inLine == *listHead) 73 | *listHead = newLine; 74 | 75 | newLine->next = inLine->next; 76 | newLine->prev = inLine->prev; 77 | 78 | if (newLine->next) 79 | newLine->next->prev = newLine; 80 | 81 | if (newLine->prev) 82 | newLine->prev->next = newLine; 83 | 84 | if (inLine->chars) 85 | free(inLine->chars); 86 | 87 | free(inLine); 88 | } 89 | 90 | // printLinesFromList: 91 | // ---------------------------------------------------------------------------- 92 | // Print our modified lines to a FILE*. The FILE* is a real file in the GUI 93 | // target, and stdout in the CLI target. 94 | 95 | - (BOOL)printLinesFromList: (Line64*)listHead 96 | { 97 | FILE* outFile = NULL; 98 | 99 | // In the CLI target, mOutputFilePath is nil. 100 | if (iOutputFilePath) 101 | { 102 | const char* outPath = UTF8STRING(iOutputFilePath); 103 | outFile = fopen(outPath, "w"); 104 | } 105 | else 106 | outFile = stdout; 107 | 108 | if (!outFile) 109 | { 110 | perror("otx: unable to open output file"); 111 | return NO; 112 | } 113 | 114 | Line64* theLine = listHead; 115 | 116 | // Cache the fileno and use SYS_write for maximum speed. 117 | SInt32 fileNum = fileno(outFile); 118 | 119 | while (theLine) 120 | { 121 | if (syscall(SYS_write, fileNum, theLine->chars, theLine->length) == -1) 122 | { 123 | perror("otx: unable to write to output file"); 124 | 125 | if (iOutputFilePath) 126 | { 127 | if (fclose(outFile) != 0) 128 | perror("otx: unable to close output file"); 129 | } 130 | 131 | return NO; 132 | } 133 | 134 | theLine = theLine->next; 135 | } 136 | 137 | if (iOutputFilePath) 138 | { 139 | if (fclose(outFile) != 0) 140 | { 141 | perror("otx: unable to close output file"); 142 | return NO; 143 | } 144 | } 145 | 146 | return YES; 147 | } 148 | 149 | // deleteLinesFromList: 150 | // ---------------------------------------------------------------------------- 151 | 152 | - (void)deleteLinesFromList: (Line64*)listHead 153 | { 154 | Line64* theLine = listHead; 155 | 156 | while (theLine) 157 | { 158 | if (theLine->prev) // If there's one behind us... 159 | { 160 | free(theLine->prev->chars); // delete it. 161 | free(theLine->prev); 162 | } 163 | 164 | if (theLine->next) // If there are more... 165 | theLine = theLine->next; // jump to next one and continue. 166 | else 167 | { // This is the last one, delete it. 168 | free(theLine->chars); 169 | free(theLine); 170 | theLine = NULL; 171 | } 172 | } 173 | } 174 | 175 | // deleteLinesBefore:fromList: 176 | // ---------------------------------------------------------------------------- 177 | 178 | - (void)deleteLinesBefore: (Line64*)inLine 179 | fromList: (Line64**)listHead 180 | { 181 | Line64* theLine = *listHead; 182 | 183 | while (theLine) 184 | { 185 | if (theLine->prev) // If there's one behind us... 186 | { 187 | free(theLine->prev->chars); // delete it. 188 | free(theLine->prev); 189 | } 190 | 191 | if (theLine->next && theLine->next != inLine) // If there are more... 192 | theLine = theLine->next; // jump to next one and continue. 193 | else 194 | { // This is the last one, delete it. 195 | free(theLine->chars); 196 | free(theLine); 197 | theLine = NULL; 198 | } 199 | } 200 | 201 | // Update the head. 202 | *listHead = inLine; 203 | (*listHead)->prev = NULL; 204 | } 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /src/English.lproj/Help/Contents/toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | otx Help: TOC 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 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 | 56 | 57 | 58 | 59 |
otx Help
Preferences
 Show local offsets
 Show data sections
 Entab output
 Show md5 checksum
 Demangle names
 Show method types
 Show variable types
 Filename
 Location
 Open file with application
60 | 61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/source/Categories/Searchers.m: -------------------------------------------------------------------------------- 1 | /* 2 | Searchers.m 3 | 4 | A category on Exe32Processor that contains the various binary search 5 | methods. 6 | 7 | This file is in the public domain. 8 | */ 9 | 10 | #import 11 | 12 | #import "Searchers.h" 13 | #import "ObjcAccessors.h" 14 | 15 | @implementation Exe32Processor(Searchers) 16 | 17 | // findSymbolByAddress: 18 | // ---------------------------------------------------------------------------- 19 | 20 | - (char*)findSymbolByAddress: (uint32_t)inAddress 21 | { 22 | if (!iFuncSyms) 23 | return NO; 24 | 25 | nlist searchKey = {{0}, 0, 0, 0, inAddress}; 26 | nlist* symbol = (nlist*)bsearch(&searchKey, 27 | iFuncSyms, iNumFuncSyms, sizeof(nlist), 28 | (COMPARISON_FUNC_TYPE)Sym_Compare); 29 | 30 | if (symbol) { 31 | return (char*)((char *)iMachHeaderPtr + iStringTableOffset + symbol->n_un.n_strx); 32 | }else 33 | return NULL; 34 | } 35 | 36 | // findClassMethod:byAddress: 37 | // ---------------------------------------------------------------------------- 38 | 39 | - (BOOL)findClassMethod: (MethodInfo**)outMI 40 | byAddress: (uint32_t)inAddress; 41 | { 42 | if (!outMI) 43 | return NO; 44 | 45 | if (!iClassMethodInfos) 46 | { 47 | *outMI = NULL; 48 | return NO; 49 | } 50 | 51 | uint32_t swappedAddress = inAddress; 52 | 53 | if (iSwapped) 54 | swappedAddress = OSSwapInt32(swappedAddress); 55 | 56 | MethodInfo searchKey = {0}; 57 | searchKey.m.method_imp = swappedAddress; 58 | 59 | *outMI = bsearch(&searchKey, 60 | iClassMethodInfos, iNumClassMethodInfos, sizeof(MethodInfo), 61 | (COMPARISON_FUNC_TYPE) 62 | (iSwapped ? MethodInfo_Compare_Swapped : MethodInfo_Compare)); 63 | 64 | return (*outMI != NULL); 65 | } 66 | 67 | // findCatMethod:byAddress: 68 | // ---------------------------------------------------------------------------- 69 | 70 | - (BOOL)findCatMethod: (MethodInfo**)outMI 71 | byAddress: (uint32_t)inAddress; 72 | { 73 | if (!outMI) 74 | return NO; 75 | 76 | if (!iCatMethodInfos) 77 | { 78 | *outMI = NULL; 79 | return NO; 80 | } 81 | 82 | uint32_t swappedAddress = inAddress; 83 | 84 | if (iSwapped) 85 | swappedAddress = OSSwapInt32(swappedAddress); 86 | 87 | MethodInfo searchKey = {0}; 88 | searchKey.m.method_imp = swappedAddress; 89 | 90 | *outMI = bsearch(&searchKey, 91 | iCatMethodInfos, iNumCatMethodInfos, sizeof(MethodInfo), 92 | (COMPARISON_FUNC_TYPE) 93 | (iSwapped ? MethodInfo_Compare_Swapped : MethodInfo_Compare)); 94 | 95 | return (*outMI != NULL); 96 | } 97 | 98 | // findIvar:inClass:withOffset: 99 | // ---------------------------------------------------------------------------- 100 | 101 | - (BOOL)findIvar: (objc1_32_ivar*)outIvar 102 | inClass: (objc1_32_class*)inClass 103 | withOffset: (uint32_t)inOffset 104 | { 105 | if (!inClass || !outIvar) 106 | return NO; 107 | 108 | // Loop thru inClass and all superclasses. 109 | objc1_32_class* theClassPtr = inClass; 110 | objc1_32_class theSwappedClass = *theClassPtr; 111 | objc1_32_class theDummyClass = {0}; 112 | char* theSuperName = NULL; 113 | objc1_32_ivar_list* theIvars; 114 | 115 | while (theClassPtr) 116 | { 117 | // if (mSwapped) 118 | // swap_objc_class(&theSwappedClass); 119 | 120 | theIvars = (objc1_32_ivar_list*)[self getPointer:theSwappedClass.ivars type:NULL]; 121 | 122 | if (!theIvars) 123 | { // Try again with the superclass. 124 | theSuperName = [self getPointer:theClassPtr->super_class type:NULL]; 125 | 126 | if (!theSuperName) 127 | break; 128 | 129 | if (![self getObjc1Class:&theDummyClass fromName:theSuperName]) 130 | break; 131 | 132 | theClassPtr = &theDummyClass; 133 | 134 | continue; 135 | } 136 | 137 | uint32_t numIvars = theIvars->ivar_count; 138 | 139 | if (iSwapped) 140 | numIvars = OSSwapInt32(numIvars); 141 | 142 | // It would be nice to use bsearch(3) here, but there's too much 143 | // swapping. 144 | SInt64 begin = 0; 145 | SInt64 end = numIvars - 1; 146 | SInt64 split = numIvars / 2; 147 | uint32_t offset; 148 | 149 | while (end >= begin) 150 | { 151 | offset = theIvars->ivar_list[split].ivar_offset; 152 | 153 | if (iSwapped) 154 | offset = OSSwapInt32(offset); 155 | 156 | if (offset == inOffset) 157 | { 158 | *outIvar = theIvars->ivar_list[split]; 159 | 160 | if (iSwapped) 161 | swap_objc1_32_ivar(outIvar); 162 | 163 | return YES; 164 | } 165 | 166 | if (offset > inOffset) 167 | end = split - 1; 168 | else 169 | begin = split + 1; 170 | 171 | split = (begin + end) / 2; 172 | } 173 | 174 | // Try again with the superclass. 175 | theSuperName = [self getPointer:theClassPtr->super_class type:NULL]; 176 | 177 | if (!theSuperName) 178 | break; 179 | 180 | if (![self getObjc1Class:&theDummyClass fromName:theSuperName]) 181 | break; 182 | 183 | theClassPtr = &theDummyClass; 184 | } 185 | 186 | return NO; 187 | } 188 | 189 | // findIvar:inClass:withOffset: 190 | // ---------------------------------------------------------------------------- 191 | 192 | - (BOOL)findIvar: (objc2_32_ivar_t**)outIvar 193 | inClass2: (objc2_32_class_t*)inClass 194 | withOffset: (uint32_t)inOffset 195 | { 196 | if (!inClass || !outIvar) 197 | return NO; 198 | 199 | objc2_64_ivar_t searchKey = {inOffset, 0, 0, 0, 0}; 200 | 201 | *outIvar = bsearch(&searchKey, iClassIvars, iNumClassIvars, sizeof(objc2_32_ivar_t), 202 | (COMPARISON_FUNC_TYPE)objc2_32_ivar_t_Compare); 203 | 204 | return (*outIvar != NULL); 205 | } 206 | 207 | @end 208 | -------------------------------------------------------------------------------- /src/source/ObjcTypes.m: -------------------------------------------------------------------------------- 1 | /* 2 | ObjcTypes.m 3 | 4 | Definitions shared by GUI and CLI targets. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | 10 | #import "ObjcTypes.h" 11 | 12 | 13 | void swap_objc1_32_module(objc1_32_module *m) 14 | { 15 | m->version = OSSwapInt32(m->version); 16 | m->size = OSSwapInt32(m->size); 17 | m->name = OSSwapInt32(m->name); 18 | m->symtab = OSSwapInt32(m->symtab); 19 | } 20 | 21 | 22 | void swap_objc1_32_symtab(objc1_32_symtab *s) 23 | { 24 | s->sel_ref_cnt = OSSwapInt32(s->sel_ref_cnt); 25 | s->refs = OSSwapInt32(s->refs); 26 | s->cls_def_cnt = OSSwapInt16(s->cls_def_cnt); 27 | s->cat_def_cnt = OSSwapInt16(s->cat_def_cnt); 28 | } 29 | 30 | 31 | void swap_objc1_32_class(objc1_32_class *c) 32 | { 33 | c->isa = OSSwapInt32(c->isa); 34 | c->super_class = OSSwapInt32(c->super_class); 35 | c->name = OSSwapInt32(c->name); 36 | c->version = OSSwapInt32(c->version); 37 | c->info = OSSwapInt32(c->info); 38 | c->instance_size = OSSwapInt32(c->instance_size); 39 | c->ivars = OSSwapInt32(c->ivars); 40 | c->methodLists = OSSwapInt32(c->methodLists); 41 | c->cache = OSSwapInt32(c->cache); 42 | c->protocols = OSSwapInt32(c->protocols); 43 | } 44 | 45 | 46 | void swap_objc1_32_ivar(objc1_32_ivar *i) 47 | { 48 | i->ivar_name = OSSwapInt32(i->ivar_name); 49 | i->ivar_type = OSSwapInt32(i->ivar_type); 50 | i->ivar_offset = OSSwapInt32(i->ivar_offset); 51 | } 52 | 53 | 54 | void swap_objc1_32_category(objc1_32_category *c) 55 | { 56 | c->category_name = OSSwapInt32(c->category_name); 57 | c->class_name = OSSwapInt32(c->class_name); 58 | c->instance_methods = OSSwapInt32(c->instance_methods); 59 | c->class_methods = OSSwapInt32(c->class_methods); 60 | c->protocols = OSSwapInt32(c->protocols); 61 | } 62 | 63 | 64 | void swap_objc1_32_method_list(objc1_32_method_list *m) 65 | { 66 | m->obsolete = OSSwapInt32(m->obsolete); 67 | m->method_count = OSSwapInt32(m->method_count); 68 | } 69 | 70 | 71 | void swap_objc1_32_method(objc1_32_method *m) 72 | { 73 | m->method_name = OSSwapInt32(m->method_name); 74 | m->method_types = OSSwapInt32(m->method_types); 75 | m->method_imp = OSSwapInt32(m->method_imp); 76 | } 77 | 78 | 79 | void swap_objc1_64_module(objc1_64_module *m) 80 | { 81 | m->version = OSSwapInt64(m->version); 82 | m->size = OSSwapInt64(m->size); 83 | m->name = OSSwapInt64(m->name); 84 | m->symtab = OSSwapInt64(m->symtab); 85 | } 86 | 87 | 88 | void swap_objc1_64_symtab(objc1_64_symtab *s) 89 | { 90 | s->sel_ref_cnt = OSSwapInt64(s->sel_ref_cnt); 91 | s->refs = OSSwapInt64(s->refs); 92 | s->cls_def_cnt = OSSwapInt16(s->cls_def_cnt); 93 | s->cat_def_cnt = OSSwapInt16(s->cat_def_cnt); 94 | } 95 | 96 | 97 | void swap_objc1_64_class(objc1_64_class *c) 98 | { 99 | c->isa = OSSwapInt64(c->isa); 100 | c->super_class = OSSwapInt64(c->super_class); 101 | c->name = OSSwapInt64(c->name); 102 | c->version = OSSwapInt64(c->version); 103 | c->info = OSSwapInt64(c->info); 104 | c->instance_size = OSSwapInt64(c->instance_size); 105 | c->ivars = OSSwapInt64(c->ivars); 106 | c->methodLists = OSSwapInt64(c->methodLists); 107 | c->cache = OSSwapInt64(c->cache); 108 | c->protocols = OSSwapInt64(c->protocols); 109 | } 110 | 111 | 112 | void swap_objc1_64_ivar(objc1_64_ivar *i) 113 | { 114 | i->ivar_name = OSSwapInt64(i->ivar_name); 115 | i->ivar_type = OSSwapInt64(i->ivar_type); 116 | i->ivar_offset = OSSwapInt64(i->ivar_offset); 117 | } 118 | 119 | 120 | void swap_objc1_64_category(objc1_64_category *c) 121 | { 122 | c->category_name = OSSwapInt64(c->category_name); 123 | c->class_name = OSSwapInt64(c->class_name); 124 | c->instance_methods = OSSwapInt64(c->instance_methods); 125 | c->class_methods = OSSwapInt64(c->class_methods); 126 | c->protocols = OSSwapInt64(c->protocols); 127 | } 128 | 129 | 130 | void swap_objc1_64_method_list(objc1_64_method_list *m) 131 | { 132 | m->obsolete = OSSwapInt64(m->obsolete); 133 | m->method_count = OSSwapInt64(m->method_count); 134 | } 135 | 136 | 137 | void swap_objc1_64_method(objc1_64_method *m) 138 | { 139 | m->method_name = OSSwapInt64(m->method_name); 140 | m->method_types = OSSwapInt64(m->method_types); 141 | m->method_imp = OSSwapInt64(m->method_imp); 142 | } 143 | 144 | 145 | void swap_objc2_32_class(objc2_32_class_t *c) 146 | { 147 | c->isa = OSSwapInt32(c->isa); 148 | c->superclass = OSSwapInt32(c->superclass); 149 | c->cache = OSSwapInt32(c->cache); 150 | c->vtable = OSSwapInt32(c->vtable); 151 | c->data = OSSwapInt32(c->data); 152 | } 153 | 154 | 155 | void swap_objc2_32_method(objc2_32_method_t *m) 156 | { 157 | m->name = OSSwapInt32(m->name); 158 | m->types = OSSwapInt32(m->types); 159 | m->imp = OSSwapInt32(m->imp); 160 | } 161 | 162 | 163 | void swap_objc2_32_ivar(objc2_32_ivar_t *i) 164 | { 165 | i->offset = OSSwapInt64(i->offset); 166 | i->name = OSSwapInt32(i->name); 167 | i->type = OSSwapInt32(i->type); 168 | i->alignment = OSSwapInt32(i->alignment); 169 | i->size = OSSwapInt32(i->size); 170 | } 171 | 172 | 173 | void swap_objc2_64_class(objc2_64_class_t *c) 174 | { 175 | c->isa = OSSwapInt64(c->isa); 176 | c->superclass = OSSwapInt64(c->superclass); 177 | c->cache = OSSwapInt64(c->cache); 178 | c->vtable = OSSwapInt64(c->vtable); 179 | c->data = OSSwapInt64(c->data); 180 | } 181 | 182 | 183 | void swap_objc2_64_method(objc2_64_method_t *m) 184 | { 185 | m->name = OSSwapInt64(m->name); 186 | m->types = OSSwapInt64(m->types); 187 | m->imp = OSSwapInt64(m->imp); 188 | } 189 | 190 | 191 | void swap_objc2_64_ivar(objc2_64_ivar_t *i) 192 | { 193 | i->offset = OSSwapInt64(i->offset); 194 | i->name = OSSwapInt64(i->name); 195 | i->type = OSSwapInt64(i->type); 196 | i->alignment = OSSwapInt32(i->alignment); 197 | i->size = OSSwapInt32(i->size); 198 | } 199 | 200 | -------------------------------------------------------------------------------- /src/source/AppController.h: -------------------------------------------------------------------------------- 1 | /* 2 | AppController.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #import "DropBox.h" 10 | #import "ErrorReporter.h" 11 | #import "ProgressReporter.h" 12 | 13 | #define kOutputTextTag 100 14 | #define kOutputFileBaseTag 200 15 | #define kOutputFileExtTag 201 16 | 17 | #define kPrefsAnimationTime 0.12 18 | #define kMainAnimationTime 0.15 19 | 20 | #define NSXViewAnimationCustomEffectsKey @"NSXViewAnimationCustomEffectsKey" 21 | 22 | // There can be only one swap effect per animation in this implementation. 23 | #define NSXViewAnimationSwapAtBeginningEffect (1 << 0) 24 | #define NSXViewAnimationSwapAtEndEffect (1 << 1) 25 | #define NSXViewAnimationSwapAtBeginningAndEndEffect (1 << 2) 26 | #define NSXViewAnimationFadeOutAndSwapEffect (1 << 3) 27 | 28 | // These effects can be combined. 29 | #define NSXViewAnimationUpdateResizeMasksAtEndEffect (1 << 10) 30 | #define NSXViewAnimationUpdateWindowMinMaxSizesAtEndEffect (1 << 11) 31 | #define NSXViewAnimationPerformSelectorAtEndEffect (1 << 12) 32 | #define NSXViewAnimationOpenFileWithAppAtEndEffect (1 << 13) 33 | 34 | #define NSXViewAnimationSwapOldKey \ 35 | @"NSXViewAnimationSwapOldKey" // NSView* 36 | #define NSXViewAnimationSwapNewKey \ 37 | @"NSXViewAnimationSwapNewKey" // NSView* 38 | 39 | #define NSXViewAnimationResizeMasksArrayKey \ 40 | @"NSXViewAnimationResizeMasksArrayKey" // NSArray* (uint32_t) 41 | #define NSXViewAnimationResizeViewsArrayKey \ 42 | @"NSXViewAnimationResizeViewsArrayKey" // NSArray* (uint32_t) 43 | 44 | #define NSXViewAnimationWindowMinSizeKey \ 45 | @"NSXViewAnimationWindowMinSizeKey" // NSValue* (NSSize*) 46 | #define NSXViewAnimationWindowMaxSizeKey \ 47 | @"NSXViewAnimationWindowMaxSizeKey" // NSValue* (NSSize*) 48 | 49 | #define NSXViewAnimationSelectorKey \ 50 | @"NSXViewAnimationSelectorKey" // NSValue* (SEL) 51 | #define NSXViewAnimationPerformInNewThreadKey \ 52 | @"NSXViewAnimationPerformInNewThreadKey" // NSNumber* (BOOL) 53 | 54 | #define NSXViewAnimationFilePathKey \ 55 | @"NSXViewAnimationFilePathKey" // NSString* 56 | #define NSXViewAnimationAppNameKey \ 57 | @"NSXViewAnimationAppNameKey" // NSString* 58 | 59 | #define OTXPrefsToolbarID @"OTX Preferences Window Toolbar" 60 | #define PrefsGeneralToolbarItemID @"General Toolbar Item" 61 | #define PrefsOutputToolbarItemID @"Output Toolbar Item" 62 | 63 | #define PrefsToolbarItemsArray \ 64 | [NSArray arrayWithObjects: PrefsGeneralToolbarItemID, \ 65 | PrefsOutputToolbarItemID, nil] 66 | 67 | typedef struct 68 | { 69 | cpu_type_t type; 70 | cpu_subtype_t subtype; 71 | } 72 | CPUID; 73 | 74 | // ============================================================================ 75 | 76 | @interface AppController : NSObject 77 | { 78 | @private 79 | // main window 80 | IBOutlet NSWindow* iMainWindow; 81 | IBOutlet NSPopUpButton* iArchPopup; 82 | IBOutlet NSButton* iThinButton; 83 | IBOutlet NSButton* iVerifyButton; 84 | IBOutlet NSTextField* iOutputText; 85 | IBOutlet NSTextField* iOutputLabelText; 86 | IBOutlet NSTextField* iPathText; 87 | IBOutlet NSTextField* iPathLabelText; 88 | IBOutlet NSTextField* iProgText; 89 | IBOutlet NSTextField* iTypeText; 90 | IBOutlet NSTextField* iTypeLabelText; 91 | IBOutlet NSProgressIndicator* iProgBar; 92 | IBOutlet NSButton* iSaveButton; 93 | IBOutlet DropBox* iDropBox; 94 | IBOutlet NSView* iMainView; 95 | IBOutlet NSView* iProgView; 96 | 97 | // prefs window 98 | IBOutlet NSWindow* iPrefsWindow; 99 | IBOutlet NSView* iPrefsGeneralView; 100 | IBOutlet NSView* iPrefsOutputView; 101 | 102 | NSURL* iObjectFile; 103 | cpu_type_t iSelectedArchCPUType; 104 | cpu_subtype_t iSelectedArchCPUSubType; 105 | CPUID iCPUIDs[4]; // refcons for iArchPopup 106 | uint32_t iFileArchMagic; 107 | BOOL iFileIsValid; 108 | BOOL iIgnoreArch; 109 | BOOL iExeIsFat; 110 | BOOL iProcessing; 111 | NSString* iExeName; 112 | NSString* iOutputFileLabel; 113 | NSString* iOutputFileName; 114 | NSString* iOutputFilePath; 115 | NSView** iPrefsViews; 116 | uint32_t iPrefsCurrentViewIndex; 117 | host_basic_info_data_t iHostInfo; 118 | NSShadow* iTextShadow; 119 | NSTimer* iIndeterminateProgBarMainThreadTimer; 120 | } 121 | 122 | // main window 123 | - (void)setupMainWindow; 124 | - (IBAction)showMainWindow: (id)sender; 125 | - (void)applyShadowToText: (NSTextField*)inText; 126 | - (IBAction)selectArch: (id)sender; 127 | - (IBAction)openExe: (id)sender; 128 | - (IBAction)syncOutputText: (id)sender; 129 | - (IBAction)attemptToProcessFile: (id)sender; 130 | - (IBAction)cancel: (id)sender; 131 | - (void)processFile; 132 | - (void)continueProcessingFile; 133 | - (void)adjustInterfaceForMultiThread; 134 | - (void)adjustInterfaceForSingleThread; 135 | - (void)processingThreadDidFinish: (NSString*)result; 136 | - (void)nudgeIndeterminateProgBar: (NSTimer*)timer; 137 | 138 | - (IBAction)thinFile: (id)sender; 139 | - (IBAction)verifyNops: (id)sender; 140 | 141 | - (void)refreshMainWindow; 142 | - (void)syncSaveButton; 143 | 144 | - (void)newPackageFile: (NSURL*)inPackageFile; 145 | - (void)newOFile: (NSURL*)inOFile 146 | needsPath: (BOOL)inNeedsPath; 147 | - (void)nopAlertDidEnd: (NSAlert*)alert 148 | returnCode: (int)returnCode 149 | contextInfo: (void*)contextInfo; 150 | - (void)showProgView; 151 | - (void)hideProgView: (BOOL)inAnimate 152 | openFile: (BOOL)inOpenFile; 153 | 154 | - (void)dupeFileAlertDidEnd: (NSAlert*)alert 155 | returnCode: (int)returnCode 156 | contextInfo: (void*)contextInfo; 157 | 158 | // prefs window 159 | - (void)setupPrefsWindow; 160 | - (IBAction)showPrefs: (id)sender; 161 | - (IBAction)switchPrefsViews: (id)sender; 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /src/source/Categories/Objc64Accessors.m: -------------------------------------------------------------------------------- 1 | /* 2 | Objc64Accessors.m 3 | 4 | What the filename says. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "Objc64Accessors.h" 12 | #import "Searchers64.h" 13 | 14 | @implementation Exe64Processor(Objc64Accessors) 15 | 16 | // getObjcClassPtr:fromMethod: 17 | // ---------------------------------------------------------------------------- 18 | // Given a method imp address, return the class to which it belongs. This func 19 | // is called each time a new function is detected. If that function is known 20 | // to be an Obj-C method, it's class is returned. Otherwise this returns NULL. 21 | 22 | - (BOOL)getObjcClassPtr: (objc2_64_class_t**)outClass 23 | fromMethod: (UInt64)inAddress; 24 | { 25 | *outClass = NULL; 26 | 27 | Method64Info* theInfo = NULL; 28 | [self findClassMethod:&theInfo byAddress:inAddress]; 29 | 30 | if (theInfo) 31 | *outClass = &theInfo->oc_class; 32 | 33 | return (*outClass != NULL); 34 | } 35 | 36 | // getObjcMethod:fromAddress: 37 | // ---------------------------------------------------------------------------- 38 | // Given a method imp address, return the MethodInfo for it. 39 | 40 | - (BOOL)getObjcMethod: (Method64Info**)outMI 41 | fromAddress: (UInt64)inAddress; 42 | { 43 | *outMI = NULL; 44 | [self findClassMethod:outMI byAddress:inAddress]; 45 | 46 | /* if (*outMI) 47 | return YES; 48 | 49 | [self findCatMethod:outMI byAddress:inAddress];*/ 50 | 51 | return (*outMI != NULL); 52 | } 53 | 54 | // getObjcMethodList:methods:fromAddress: (was get_method_list) 55 | // ---------------------------------------------------------------------------- 56 | // Removed the truncation flag. 'left' is no longer used by the caller. 57 | 58 | - (BOOL)getObjcMethodList: (objc2_64_method_list_t*)outList 59 | methods: (objc2_64_method_t**)outMethods 60 | fromAddress: (UInt64)inAddress; 61 | { 62 | /* uint32_t left, i; 63 | 64 | if (!outList) 65 | return NO; 66 | 67 | *outList = (objc_method_list){0}; 68 | 69 | for (i = 0; i < iNumObjcSects; i++) 70 | { 71 | if (inAddress >= iObjcSects[i].s.addr && 72 | inAddress < iObjcSects[i].s.addr + iObjcSects[i].s.size) 73 | { 74 | left = iObjcSects[i].s.size - 75 | (inAddress - iObjcSects[i].s.addr); 76 | 77 | if (left >= sizeof(objc_method_list) - sizeof(objc_method)) 78 | { 79 | memcpy(outList, iObjcSects[i].contents + 80 | (inAddress - iObjcSects[i].s.addr), 81 | sizeof(objc_method_list) - sizeof(objc_method)); 82 | left -= sizeof(objc_method_list) - 83 | sizeof(objc_method); 84 | *outMethods = (objc_method*)(iObjcSects[i].contents + 85 | (inAddress - iObjcSects[i].s.addr) + 86 | sizeof(objc_method_list) - sizeof(objc_method)); 87 | } 88 | else 89 | { 90 | memcpy(outList, iObjcSects[i].contents + 91 | (inAddress - iObjcSects[i].s.addr), left); 92 | left = 0; 93 | *outMethods = NULL; 94 | } 95 | 96 | return YES; 97 | } 98 | } 99 | 100 | return NO; 101 | */ 102 | return NO; 103 | } 104 | 105 | // getObjcDescription:fromObject:type: 106 | // ---------------------------------------------------------------------------- 107 | // Given an Obj-C object, return it's description. 108 | 109 | - (BOOL)getObjcDescription: (char**)outDescription 110 | fromObject: (const char*)inObject 111 | type: (UInt8)inType 112 | { 113 | *outDescription = NULL; 114 | 115 | UInt64 theValue = 0; 116 | 117 | switch (inType) 118 | { 119 | case CFStringType: 120 | { 121 | cfstring_object_64 cfString = *(cfstring_object_64*)inObject; 122 | 123 | if (cfString.oc_string.length == 0) 124 | break; 125 | 126 | theValue = cfString.oc_string.chars; 127 | 128 | break; 129 | } 130 | 131 | case OCStrObjectType: 132 | { 133 | nxstring_object_64 ocString = *(nxstring_object_64*)inObject; 134 | 135 | if (ocString.length == 0) 136 | break; 137 | 138 | theValue = ocString.chars; 139 | 140 | break; 141 | } 142 | 143 | case OCGenericType: 144 | theValue = *(UInt64*)inObject; 145 | 146 | break; 147 | 148 | default: 149 | return NO; 150 | break; 151 | } 152 | 153 | if (iSwapped) 154 | theValue = OSSwapInt64(theValue); 155 | 156 | *outDescription = [self getPointer:theValue type:NULL]; 157 | 158 | return (*outDescription != NULL); 159 | } 160 | 161 | // getObjcClass:fromName: 162 | // ---------------------------------------------------------------------------- 163 | // Given a class name, return the class itself. This func is used to tie 164 | // categories to classes. We have 2 pointers to the same name, so pointer 165 | // equality is sufficient. 166 | 167 | - (BOOL)getObjcClass: (objc2_64_class_t*)outClass 168 | fromName: (const char*)inName; 169 | { 170 | uint32_t i; 171 | UInt64 namePtr; 172 | 173 | for (i = 0; i < iNumClassMethodInfos; i++) 174 | { 175 | objc2_64_class_ro_t* roData = (objc2_64_class_ro_t*)(iDataSect.contents + 176 | (uintptr_t)(iClassMethodInfos[i].oc_class.data - iDataSect.s.addr)); 177 | 178 | namePtr = roData->name; 179 | 180 | if (iSwapped) 181 | namePtr = OSSwapInt64(namePtr); 182 | 183 | if ([self getPointer:namePtr type:NULL] == inName) 184 | { 185 | *outClass = iClassMethodInfos[i].oc_class; 186 | return YES; 187 | } 188 | } 189 | 190 | *outClass = (objc2_64_class_t){0}; 191 | return NO; 192 | } 193 | 194 | // getObjcClassPtr:fromName: 195 | // ---------------------------------------------------------------------------- 196 | // Same as above, but returns a pointer. 197 | 198 | - (BOOL)getObjcClassPtr: (objc2_64_class_t**)outClassPtr 199 | fromName: (const char*)inName; 200 | { 201 | uint32_t i; 202 | UInt64 namePtr; 203 | 204 | for (i = 0; i < iNumClassMethodInfos; i++) 205 | { 206 | objc2_64_class_ro_t* roData = (objc2_64_class_ro_t*)(iDataSect.contents + 207 | (uintptr_t)(iClassMethodInfos[i].oc_class.data - iDataSect.s.addr)); 208 | 209 | namePtr = roData->name; 210 | 211 | if (iSwapped) 212 | namePtr = OSSwapInt64(namePtr); 213 | 214 | if ([self getPointer:namePtr type:NULL] == inName) 215 | { 216 | *outClassPtr = &iClassMethodInfos[i].oc_class; 217 | return YES; 218 | } 219 | } 220 | 221 | *outClassPtr = NULL; 222 | return NO; 223 | } 224 | 225 | // getObjcMetaClass:fromClass: 226 | // ---------------------------------------------------------------------------- 227 | 228 | - (BOOL)getObjcMetaClass: (objc2_64_class_t*)outClass 229 | fromClass: (objc2_64_class_t*)inClass; 230 | { 231 | /* if (inClass->isa >= iMetaClassSect.s.addr && 232 | inClass->isa < iMetaClassSect.s.addr + iMetaClassSect.s.size) 233 | { 234 | *outClass = *(objc_class*)(iMetaClassSect.contents + 235 | (inClass->isa - iMetaClassSect.s.addr)); 236 | 237 | return YES; 238 | }*/ 239 | 240 | return NO; 241 | } 242 | 243 | @end 244 | -------------------------------------------------------------------------------- /src/source/Processors/Exe64Processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | Exe64Processor.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #import "ExeProcessor.h" 10 | 11 | /* MethodInfo 12 | 13 | Additional info pertaining to an Obj-C method. 14 | */ 15 | typedef struct 16 | { 17 | objc2_64_method_t m; 18 | objc2_64_class_t oc_class; 19 | BOOL inst; // to determine '+' or '-' 20 | } 21 | Method64Info; 22 | 23 | /* GP64RegisterInfo 24 | 25 | Processor-specific subclasses maintain arrays of RegisterInfo's to 26 | simulate the state of registers in the CPU as each line of code is 27 | executed. 28 | */ 29 | typedef struct 30 | { 31 | UInt64 value; 32 | BOOL isValid; // value can be trusted 33 | objc2_64_class_t* classPtr; 34 | char* className; 35 | char* messageRefSel; // selector for calls through pointers 36 | } 37 | GP64RegisterInfo; 38 | 39 | /* Var64Info 40 | 41 | Represents a local variable in the stack frame. Currently, copies of 42 | 'self' are maintained in the variable-sized array mLocalSelves, and 43 | variables pushed onto the stack in x86 code are maintained in the array 44 | mStack[MAX_STACK_SIZE]. May be used for other things in future. 45 | 46 | Note the semantic differences regarding stack frames: 47 | 48 | PPC x86 49 | -------------------------------------------------- 50 | local vars stack ptr(r1) + offset base ptr(EBP) - offset 51 | args to current func --- base ptr(EBP) + offset 52 | args to called func --- stack ptr(ESP) + offset 53 | */ 54 | typedef struct 55 | { 56 | GP64RegisterInfo regInfo; 57 | SInt32 offset; 58 | } 59 | Var64Info; 60 | 61 | /* Line64Info 62 | 63 | Used exclusively in the Line64 struct below, LineInfo encapsulates the 64 | details pertaining to a line of disassemled code that are not part 65 | of the basic linked list element. 66 | */ 67 | typedef struct 68 | { 69 | UInt64 address; 70 | UInt8 code[16]; // machine code as int bytes 71 | UInt8 codeLength; 72 | BOOL isCode; // NO for function names, section names etc. 73 | BOOL isFunction; // YES if this is the first instruction in a function. 74 | BOOL isFunctionEnd; // YES if this is the last instruction in a function. 75 | } 76 | Line64Info; 77 | 78 | /* Line64 79 | 80 | Represents a line of text from otool's output. For each __text section, 81 | otool is called twice- with symbolic operands(-V) and without(-v). The 82 | resulting 2 text files are each read into a doubly-linked list of Line64's. 83 | Each Line64 contains a pointer to the corresponding Line64 in the other list. 84 | The reason for this approach is due to otool's inaccuracy in guessing 85 | symbols. From comments in ofile_print.c: 86 | 87 | "Both a verbose (symbolic) and non-verbose modes are supported to aid 88 | in seeing the values even if they are not correct." 89 | 90 | With both versions on hand, we can choose the better one for each Line64. 91 | The criteria for choosing is defined in chooseLine:. This does result in a 92 | slight loss of info, in the rare case that otool guesses correctly for 93 | any instruction that is not a function call. 94 | */ 95 | struct Line64 96 | { 97 | char* chars; // C string 98 | size_t length; // C string length 99 | struct Line64* next; // next line in this list 100 | struct Line64* prev; // previous line in this list 101 | struct Line64* alt; // "this" line in the other list 102 | Line64Info info; // details 103 | }; 104 | 105 | // "typedef struct Line64" doesn't work, so we do this instead. 106 | #define Line64 struct Line64 107 | 108 | /* Machine64State 109 | 110 | Saved state of the CPU registers and local copies of self. 'localSelves' 111 | is an array with 'numLocalSelves' items. 'regInfos' is an array whose 112 | count is defined by the processor-specific subclasses. 113 | */ 114 | typedef struct 115 | { 116 | GP64RegisterInfo* regInfos; 117 | Var64Info* localSelves; 118 | uint32_t numLocalSelves; 119 | Var64Info* localVars; 120 | uint32_t numLocalVars; 121 | } 122 | Machine64State; 123 | 124 | /* Block64Info 125 | 126 | Info pertaining to a logical block of code. 'state' is the saved 127 | MachineState that should be restored upon entering this block. 128 | */ 129 | typedef struct 130 | { 131 | UInt64 beginAddress; 132 | Line64* endLine; 133 | BOOL isEpilog; 134 | Machine64State state; 135 | } 136 | Block64Info; 137 | 138 | /* Function64Info 139 | 140 | Used for tracking the changing machine states between code blocks in a 141 | function. 'blocks' is an array with 'numBlocks' items. 142 | */ 143 | typedef struct 144 | { 145 | UInt64 address; 146 | Block64Info* blocks; 147 | uint32_t numBlocks; 148 | uint32_t genericFuncNum; // 'AnonX' if > 0 149 | } 150 | Function64Info; 151 | 152 | // ============================================================================ 153 | 154 | @interface Exe64Processor : ExeProcessor 155 | { 156 | @protected 157 | // guts 158 | mach_header_64* iMachHeaderPtr; // ptr to the orig header 159 | mach_header_64 iMachHeader; // (swapped?) copy of the header 160 | Line64* iVerboseLineListHead; // linked list the first 161 | Line64* iPlainLineListHead; // linked list the second 162 | Line64** iLineArray; 163 | uint32_t iNumLines; 164 | uint32_t iNumCodeLines; 165 | cpu_type_t iArchSelector; 166 | uint64_t iCurrentFunctionStart; 167 | 168 | // base pointers for indirect addressing 169 | SInt8 iCurrentThunk; // x86 register identifier 170 | UInt64 iCurrentFuncPtr; // PPC function address 171 | 172 | // symbols that point to functions 173 | nlist_64* iFuncSyms; 174 | uint32_t iNumFuncSyms; 175 | 176 | // FunctionInfo array 177 | Function64Info* iFuncInfos; 178 | uint32_t iNumFuncInfos; 179 | 180 | // Obj-C stuff 181 | Method64Info* iClassMethodInfos; 182 | uint32_t iNumClassMethodInfos; 183 | objc2_64_ivar_t* iClassIvars; 184 | uint32_t iNumClassIvars; 185 | objc2_64_class_t* iCurrentClass; 186 | BOOL iIsInstanceMethod; 187 | 188 | // Mach-O sections 189 | section_info_64 iObjcClassListSect; 190 | section_info_64 iObjcCatListSect; // 191 | section_info_64 iObjcConstSect; 192 | section_info_64 iObjcProtoListSect; // 193 | section_info_64 iObjcSuperRefsSect; // 194 | section_info_64 iObjcClassRefsSect; 195 | section_info_64 iObjcProtoRefsSect; // 196 | section_info_64 iObjcMsgRefsSect; 197 | section_info_64 iObjcSelRefsSect; // 198 | section_info_64 iObjcDataSect; 199 | section_info_64 iCStringSect; 200 | section_info_64 iNSStringSect; 201 | section_info_64 iLit4Sect; 202 | section_info_64 iLit8Sect; 203 | section_info_64 iTextSect; 204 | section_info_64 iCoalTextSect; 205 | section_info_64 iCoalTextNTSect; 206 | section_info_64 iConstTextSect; 207 | section_info_64 iObjcMethnameSect; 208 | section_info_64 iObjcMethtypeSect; 209 | section_info_64 iObjcClassnameSect; 210 | section_info_64 iDataSect; 211 | section_info_64 iCoalDataSect; 212 | section_info_64 iCoalDataNTSect; 213 | section_info_64 iConstDataSect; 214 | section_info_64 iDyldSect; 215 | section_info_64 iCFStringSect; 216 | section_info_64 iNLSymSect; 217 | section_info_64 iImpPtrSect; 218 | UInt64 iTextOffset; 219 | UInt64 iEndOfText; 220 | } 221 | 222 | - (id)initWithURL: (NSURL*)inURL 223 | controller: (id)inController 224 | options: (ProcOptions*)inOptions; 225 | - (void)deleteFuncInfos; 226 | 227 | // processors 228 | - (BOOL)processExe: (NSString*)inOutputFilePath; 229 | - (BOOL)populateLineLists; 230 | - (BOOL)populateLineList: (Line64**)inList 231 | verbosely: (BOOL)inVerbose 232 | fromSection: (char*)inSectionName 233 | afterLine: (Line64**)inLine 234 | includingPath: (BOOL)inIncludePath; 235 | - (BOOL)printDataSections; 236 | - (void)printDataSection: (section_info_64*)inSect 237 | toFile: (FILE*)outFile; 238 | - (BOOL)lineIsCode: (const char*)inLine; 239 | 240 | // customizers 241 | - (void)gatherLineInfos; 242 | - (void)findFunctions; 243 | - (UInt64)addressFromLine: (const char*)inLine; 244 | - (void)processLine: (Line64*)ioLine; 245 | - (void)processCodeLine: (Line64**)ioLine; 246 | - (void)chooseLine: (Line64**)ioLine; 247 | - (void)entabLine: (Line64*)ioLine; 248 | - (char*)getPointer: (UInt64)inAddr 249 | type: (UInt8*)outType; 250 | 251 | - (char*)selectorForMsgSend: (char*)outComment 252 | fromLine: (Line64*)inLine; 253 | 254 | - (void)insertMD5; 255 | 256 | #ifdef OTX_DEBUG 257 | - (void)printSymbol: (nlist_64)inSym; 258 | - (void)printBlocks: (uint32_t)inFuncIndex; 259 | #endif 260 | 261 | @end 262 | 263 | // ---------------------------------------------------------------------------- 264 | // Comparison functions for qsort(3) and bsearch(3) 265 | 266 | static int 267 | Function64_Info_Compare( 268 | Function64Info* f1, 269 | Function64Info* f2) 270 | { 271 | if (f1->address < f2->address) 272 | return -1; 273 | 274 | return (f1->address > f2->address); 275 | } 276 | 277 | static int 278 | Method64Info_Compare( 279 | Method64Info* mi1, 280 | Method64Info* mi2) 281 | { 282 | if (mi1->m.imp < mi2->m.imp) 283 | return -1; 284 | 285 | return (mi1->m.imp > mi2->m.imp); 286 | } 287 | 288 | static int 289 | Method64Info_Compare_Swapped( 290 | Method64Info* mi1, 291 | Method64Info* mi2) 292 | { 293 | UInt64 imp1 = OSSwapInt64(mi1->m.imp); 294 | UInt64 imp2 = OSSwapInt64(mi2->m.imp); 295 | 296 | if (imp1 < imp2) 297 | return -1; 298 | 299 | return (imp1 > imp2); 300 | } 301 | 302 | static int 303 | objc2_64_ivar_t_Compare( 304 | objc2_64_ivar_t* i1, 305 | objc2_64_ivar_t* i2) 306 | { 307 | if (i1->offset < i2->offset) 308 | return -1; 309 | 310 | return (i1->offset > i2->offset); 311 | } 312 | 313 | // ---------------------------------------------------------------------------- 314 | // Utils 315 | 316 | static void 317 | swap_method64_info( 318 | Method64Info* mi) 319 | { 320 | swap_objc2_64_method(&mi->m); 321 | swap_objc2_64_class(&mi->oc_class); 322 | } 323 | -------------------------------------------------------------------------------- /src/source/Processors/Exe32Processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | Exe32Processor.h 3 | 4 | This file is in the public domain. 5 | */ 6 | 7 | #import 8 | 9 | #import "ExeProcessor.h" 10 | 11 | /* MethodInfo 12 | 13 | Additional info pertaining to an Obj-C method. 14 | */ 15 | typedef struct 16 | { 17 | union { 18 | struct { 19 | objc1_32_method m; 20 | objc1_32_class oc_class; 21 | objc1_32_category oc_cat; 22 | }; 23 | struct { 24 | objc2_32_method_t m2; 25 | objc2_32_class_t oc_class2; 26 | }; 27 | }; 28 | BOOL inst; // to determine '+' or '-' 29 | } 30 | MethodInfo; 31 | 32 | /* GPRegisterInfo 33 | 34 | Processor-specific subclasses maintain arrays of RegisterInfo's to 35 | simulate the state of registers in the CPU as each line of code is 36 | executed. 37 | */ 38 | typedef struct 39 | { 40 | uint32_t value; 41 | BOOL isValid; // value can be trusted 42 | objc_32_class_ptr classPtr; 43 | objc1_32_category* catPtr; 44 | } 45 | GPRegisterInfo; 46 | 47 | /* VarInfo 48 | 49 | Represents a local variable in the stack frame. Currently, copies of 50 | 'self' are maintained in the variable-sized array mLocalSelves, and 51 | variables pushed onto the stack in x86 code are maintained in the array 52 | mStack[MAX_STACK_SIZE]. May be used for other things in future. 53 | 54 | Note the semantic differences regarding stack frames: 55 | 56 | PPC x86 57 | -------------------------------------------------- 58 | local vars stack ptr(r1) + offset base ptr(EBP) - offset 59 | args to current func --- base ptr(EBP) + offset 60 | args to called func --- stack ptr(ESP) + offset 61 | */ 62 | typedef struct 63 | { 64 | GPRegisterInfo regInfo; 65 | SInt32 offset; 66 | } 67 | VarInfo; 68 | 69 | /* LineInfo 70 | 71 | Used exclusively in the Line struct below, LineInfo encapsulates the 72 | details pertaining to a line of disassemled code that are not part 73 | of the basic linked list element. 74 | */ 75 | typedef struct 76 | { 77 | uint32_t address; 78 | UInt8 code[16]; // machine code as int bytes 79 | UInt8 codeLength; 80 | BOOL isCode; // NO for function and section names etc. 81 | BOOL isFunction; // YES if this is the first instruction in a function. 82 | } 83 | LineInfo; 84 | 85 | /* Line 86 | 87 | Represents a line of text from otool's output. For each __text section, 88 | otool is called twice- with symbolic operands(-V) and without(-v). The 89 | resulting 2 text files are each read into a doubly-linked list of Line's. 90 | Each Line contains a pointer to the corresponding Line in the other list. 91 | The reason for this approach is due to otool's inaccuracy in guessing 92 | symbols. From comments in ofile_print.c: 93 | 94 | "Both a verbose (symbolic) and non-verbose modes are supported to aid 95 | in seeing the values even if they are not correct." 96 | 97 | With both versions on hand, we can choose the better one for each Line. 98 | The criteria for choosing is defined in chooseLine:. This does result in a 99 | slight loss of info, in the rare case that otool guesses correctly for 100 | any instruction that is not a function call. 101 | */ 102 | struct Line 103 | { 104 | char* chars; // C string 105 | size_t length; // C string length 106 | struct Line* next; // next line in this list 107 | struct Line* prev; // previous line in this list 108 | struct Line* alt; // "this" line in the other list 109 | LineInfo info; // details 110 | }; 111 | 112 | // "typedef struct Line" doesn't work, so we do this instead. 113 | #define Line struct Line 114 | 115 | /* MachineState 116 | 117 | Saved state of the CPU registers and local copies of self. 'localSelves' 118 | is an array with 'numLocalSelves' items. 'regInfos' is an array whose 119 | count is defined by the processor-specific subclasses. 120 | */ 121 | typedef struct 122 | { 123 | GPRegisterInfo* regInfos; 124 | VarInfo* localSelves; 125 | uint32_t numLocalSelves; 126 | VarInfo* localVars; 127 | uint32_t numLocalVars; 128 | } 129 | MachineState; 130 | 131 | /* BlockInfo 132 | 133 | Info pertaining to a logical block of code. 'state' is the saved 134 | MachineState that should be restored upon entering this block. 135 | */ 136 | typedef struct 137 | { 138 | uint32_t beginAddress; 139 | Line* endLine; 140 | BOOL isEpilog; 141 | MachineState state; 142 | } 143 | BlockInfo; 144 | 145 | /* FunctionInfo 146 | 147 | Used for tracking the changing machine states between code blocks in a 148 | function. 'blocks' is an array with 'numBlocks' items. 149 | */ 150 | typedef struct 151 | { 152 | uint32_t address; 153 | BlockInfo* blocks; 154 | uint32_t numBlocks; 155 | uint32_t genericFuncNum; // 'AnonX' if > 0 156 | } 157 | FunctionInfo; 158 | 159 | // ============================================================================ 160 | 161 | @interface Exe32Processor : ExeProcessor 162 | { 163 | @protected 164 | // guts 165 | mach_header* iMachHeaderPtr; // ptr to the orig header 166 | mach_header iMachHeader; // (swapped?) copy of the header 167 | Line* iVerboseLineListHead; // linked list the first 168 | Line* iPlainLineListHead; // linked list the second 169 | Line** iLineArray; 170 | uint32_t iNumLines; 171 | uint32_t iNumCodeLines; 172 | cpu_type_t iArchSelector; 173 | uint32_t iCurrentFunctionStart; 174 | 175 | // base pointers for indirect addressing 176 | uint32_t iCurrentFuncPtr; // PPC function address 177 | 178 | // symbols that point to functions 179 | nlist* iFuncSyms; 180 | uint32_t iNumFuncSyms; 181 | 182 | // FunctionInfo array 183 | FunctionInfo* iFuncInfos; 184 | uint32_t iNumFuncInfos; 185 | 186 | // Obj-C stuff 187 | section_info* iObjcSects; 188 | uint32_t iNumObjcSects; 189 | MethodInfo* iClassMethodInfos; 190 | uint32_t iNumClassMethodInfos; 191 | BOOL iIsInstanceMethod; 192 | uint8_t iObjcVersion; // 1 for objc1 193 | 194 | // When iObjcVersion=1, this points to a objc1_32_class 195 | // When iObjcVersion=2, this points to a objc2_32_class_t 196 | objc_32_class_ptr iCurrentClass; 197 | 198 | // Only valid when iObjcVersion=1 199 | objc1_32_category* iCurrentCat; 200 | MethodInfo* iCatMethodInfos; 201 | uint32_t iNumCatMethodInfos; 202 | 203 | // Only valid when iObjcVersion=2 204 | objc2_32_ivar_t* iClassIvars; 205 | uint32_t iNumClassIvars; 206 | 207 | // Mach-O sections 208 | section_info iCStringSect; 209 | section_info iNSStringSect; 210 | section_info iClassSect; 211 | section_info iMetaClassSect; 212 | section_info iIVarSect; 213 | section_info iObjcModSect; 214 | section_info iObjcSymSect; 215 | section_info iObjcMethnameSect; 216 | section_info iObjcMethtypeSect; 217 | section_info iObjcClassnameSect; 218 | section_info iObjcClassListSect; 219 | section_info iObjcCatListSect; 220 | section_info iObjcConstSect; 221 | section_info iObjcProtoListSect; 222 | section_info iObjcSuperRefsSect; 223 | section_info iObjcClassRefsSect; 224 | section_info iObjcProtoRefsSect; 225 | section_info iObjcMsgRefsSect; 226 | section_info iObjcSelRefsSect; 227 | section_info iObjcDataSect; 228 | section_info iLit4Sect; 229 | section_info iLit8Sect; 230 | section_info iTextSect; 231 | section_info iCoalTextSect; 232 | section_info iCoalTextNTSect; 233 | section_info iConstTextSect; 234 | section_info iDataSect; 235 | section_info iCoalDataSect; 236 | section_info iCoalDataNTSect; 237 | section_info iConstDataSect; 238 | section_info iDyldSect; 239 | section_info iCFStringSect; 240 | section_info iNLSymSect; 241 | section_info iImpPtrSect; 242 | uint32_t iTextOffset; 243 | uint32_t iEndOfText; 244 | } 245 | 246 | - (id)initWithURL: (NSURL*)inURL 247 | controller: (id)inController 248 | options: (ProcOptions*)inOptions; 249 | - (void)deleteFuncInfos; 250 | 251 | // processors 252 | - (BOOL)processExe: (NSString*)inOutputFilePath; 253 | - (BOOL)populateLineLists; 254 | - (BOOL)populateLineList: (Line**)inList 255 | verbosely: (BOOL)inVerbose 256 | fromSection: (char*)inSectionName 257 | afterLine: (Line**)inLine 258 | includingPath: (BOOL)inIncludePath; 259 | - (BOOL)printDataSections; 260 | - (void)printDataSection: (section_info*)inSect 261 | toFile: (FILE*)outFile; 262 | - (BOOL)lineIsCode: (const char*)inLine; 263 | 264 | // customizers 265 | - (void)gatherLineInfos; 266 | - (void)findFunctions; 267 | - (uint32_t)addressFromLine: (const char*)inLine; 268 | - (void)processLine: (Line*)ioLine; 269 | - (void)processCodeLine: (Line**)ioLine; 270 | - (void)chooseLine: (Line**)ioLine; 271 | - (void)entabLine: (Line*)ioLine; 272 | - (BOOL)getIvarName:(char **)outName type:(char **)outType withOffset:(uint32_t)offset inClass:(objc_32_class_ptr)classPtr; 273 | - (char*)getPointer: (uint32_t)inAddr 274 | type: (UInt8*)outType; 275 | 276 | - (char*)selectorForMsgSend: (char*)outComment 277 | fromLine: (Line*)inLine; 278 | 279 | - (void)insertMD5; 280 | 281 | #ifdef OTX_DEBUG 282 | - (void)printSymbol: (nlist)inSym; 283 | - (void)printBlocks: (uint32_t)inFuncIndex; 284 | #endif 285 | 286 | @end 287 | 288 | // ---------------------------------------------------------------------------- 289 | // Comparison functions for qsort(3) and bsearch(3) 290 | 291 | static int 292 | Function_Info_Compare( 293 | FunctionInfo* f1, 294 | FunctionInfo* f2) 295 | { 296 | if (f1->address < f2->address) 297 | return -1; 298 | 299 | return (f1->address > f2->address); 300 | } 301 | 302 | static int 303 | Line_Address_Compare( 304 | Line** l1, 305 | Line** l2) 306 | { 307 | if ((*l1)->info.address < (*l2)->info.address) 308 | return -1; 309 | 310 | return ((*l1)->info.address > (*l2)->info.address); 311 | } 312 | 313 | static int 314 | MethodInfo_Compare( 315 | MethodInfo* mi1, 316 | MethodInfo* mi2) 317 | { 318 | if (mi1->m.method_imp < mi2->m.method_imp) 319 | return -1; 320 | 321 | return (mi1->m.method_imp > mi2->m.method_imp); 322 | } 323 | 324 | static int 325 | MethodInfo_Compare_Swapped( 326 | MethodInfo* mi1, 327 | MethodInfo* mi2) 328 | { 329 | uint32_t imp1 = mi1->m.method_imp; 330 | uint32_t imp2 = mi2->m.method_imp; 331 | 332 | imp1 = OSSwapInt32(imp1); 333 | imp2 = OSSwapInt32(imp2); 334 | 335 | if (imp1 < imp2) 336 | return -1; 337 | 338 | return (imp1 > imp2); 339 | } 340 | -------------------------------------------------------------------------------- /src/source/Categories/ObjcAccessors.m: -------------------------------------------------------------------------------- 1 | /* 2 | ObjcAccessors.m 3 | 4 | What the filename says. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | #import 10 | 11 | #import "ObjcAccessors.h" 12 | #import "Searchers.h" 13 | 14 | @implementation Exe32Processor(ObjcAccessors) 15 | 16 | // getObjcClassPtr:fromMethod: 17 | // ---------------------------------------------------------------------------- 18 | // Given a method imp address, return the class to which it belongs. This func 19 | // is called each time a new function is detected. If that function is known 20 | // to be an Obj-C method, it's class is returned. Otherwise this returns NULL. 21 | 22 | - (BOOL)getObjcClassPtr: (objc_32_class_ptr*)outClass 23 | fromMethod: (uint32_t)inAddress; 24 | { 25 | *outClass = NULL; 26 | 27 | MethodInfo* theInfo = NULL; 28 | [self findClassMethod:&theInfo byAddress:inAddress]; 29 | 30 | if (theInfo) 31 | { 32 | if (iObjcVersion < 2) 33 | { 34 | *outClass = (objc_32_class_ptr)&theInfo->oc_class; 35 | } 36 | else if (iObjcVersion == 2) 37 | { 38 | *outClass = (objc_32_class_ptr)&theInfo->oc_class2; 39 | } 40 | } 41 | 42 | return (*outClass != NULL); 43 | } 44 | 45 | // getObjcClassPtr:fromName: 46 | // ---------------------------------------------------------------------------- 47 | // Given a class name, return the class itself. This func is used to tie 48 | // categories to classes. We have 2 pointers to the same name, so pointer 49 | // equality is sufficient. 50 | 51 | - (BOOL)getObjcClassPtr: (objc_32_class_ptr *)outClassPtr 52 | fromName: (const char*)inName; 53 | { 54 | if (iObjcVersion < 2) 55 | { 56 | for (uint32_t i = 0; i < iNumClassMethodInfos; i++) 57 | { 58 | uint32_t namePtr = (uint32_t)iClassMethodInfos[i].oc_class.name; 59 | 60 | if (iSwapped) 61 | namePtr = OSSwapInt32(namePtr); 62 | 63 | if ([self getPointer:namePtr type:NULL] == inName) 64 | { 65 | *outClassPtr = (objc_32_class_ptr) &iClassMethodInfos[i].oc_class; 66 | return YES; 67 | } 68 | } 69 | 70 | } 71 | else if (iObjcVersion == 2) 72 | { 73 | for (uint32_t i = 0; i < iNumClassMethodInfos; i++) 74 | { 75 | objc2_32_class_ro_t* roData = (objc2_32_class_ro_t*)(iObjcConstSect.contents + 76 | (uintptr_t)(iClassMethodInfos[i].oc_class2.data - iObjcConstSect.s.addr)); 77 | 78 | uint32_t namePtr = roData->name; 79 | 80 | if (iSwapped) 81 | namePtr = OSSwapInt32(namePtr); 82 | 83 | if ([self getPointer:namePtr type:NULL] == inName) 84 | { 85 | *outClassPtr = (objc_32_class_ptr) &iClassMethodInfos[i].oc_class2; 86 | return YES; 87 | } 88 | } 89 | } 90 | 91 | *outClassPtr = NULL; 92 | 93 | return NO; 94 | } 95 | 96 | // getObjcMethod:fromAddress: 97 | // ---------------------------------------------------------------------------- 98 | // Given a method imp address, return the MethodInfo for it. 99 | 100 | - (BOOL)getObjcMethod: (MethodInfo**)outMI 101 | fromAddress: (uint32_t)inAddress; 102 | { 103 | *outMI = NULL; 104 | 105 | [self findClassMethod:outMI byAddress:inAddress]; 106 | 107 | if (*outMI) 108 | return YES; 109 | 110 | [self findCatMethod:outMI byAddress:inAddress]; 111 | 112 | return (*outMI != NULL); 113 | } 114 | 115 | // getObjc1CatPtr:fromMethod: 116 | // ---------------------------------------------------------------------------- 117 | // Given a method imp address, return the category to which it belongs. 118 | 119 | - (BOOL)getObjc1CatPtr: (objc1_32_category**)outCat 120 | fromMethod: (uint32_t)inAddress; 121 | { 122 | *outCat = NULL; 123 | 124 | MethodInfo* theInfo = NULL; 125 | [self findCatMethod:&theInfo byAddress:inAddress]; 126 | 127 | if (theInfo) 128 | *outCat = &theInfo->oc_cat; 129 | 130 | return (*outCat != NULL); 131 | } 132 | 133 | // getObjc1MethodList:methods:fromAddress: (was get_method_list) 134 | // ---------------------------------------------------------------------------- 135 | // Removed the truncation flag. 'left' is no longer used by the caller. 136 | 137 | - (BOOL)getObjc1MethodList: (objc1_32_method_list*)outList 138 | methods: (objc1_32_method**)outMethods 139 | fromAddress: (uint32_t)inAddress; 140 | { 141 | uint32_t left, i; 142 | 143 | if (!outList) 144 | return NO; 145 | 146 | *outList = (objc1_32_method_list){0}; 147 | 148 | for (i = 0; i < iNumObjcSects; i++) 149 | { 150 | if (inAddress >= iObjcSects[i].s.addr && 151 | inAddress < iObjcSects[i].s.addr + iObjcSects[i].s.size) 152 | { 153 | left = iObjcSects[i].s.size - 154 | (inAddress - iObjcSects[i].s.addr); 155 | 156 | if (left >= sizeof(objc1_32_method_list) - sizeof(objc1_32_method)) 157 | { 158 | memcpy(outList, iObjcSects[i].contents + 159 | (inAddress - iObjcSects[i].s.addr), 160 | sizeof(objc1_32_method_list) - sizeof(objc1_32_method)); 161 | *outMethods = (objc1_32_method*)(iObjcSects[i].contents + 162 | (inAddress - iObjcSects[i].s.addr) + 163 | sizeof(objc1_32_method_list) - sizeof(objc1_32_method)); 164 | } 165 | else 166 | { 167 | memcpy(outList, iObjcSects[i].contents + 168 | (inAddress - iObjcSects[i].s.addr), left); 169 | *outMethods = NULL; 170 | } 171 | 172 | return YES; 173 | } 174 | } 175 | 176 | return NO; 177 | } 178 | 179 | // getObjc1Description:fromObject:type: 180 | // ---------------------------------------------------------------------------- 181 | // Given an Obj-C object, return it's description. 182 | 183 | - (BOOL)getObjc1Description: (char**)outDescription 184 | fromObject: (const char*)inObject 185 | type: (UInt8)inType 186 | { 187 | *outDescription = NULL; 188 | 189 | uint32_t theValue = 0; 190 | 191 | switch (inType) 192 | { 193 | case OCStrObjectType: 194 | { 195 | nxstring_object ocString = *(nxstring_object*)inObject; 196 | 197 | if (ocString.length == 0) 198 | break; 199 | 200 | theValue = ocString.chars; 201 | 202 | break; 203 | } 204 | case OCClassType: 205 | { 206 | objc1_32_class ocClass = *(objc1_32_class*)inObject; 207 | 208 | theValue = ocClass.name ? ocClass.name : ocClass.isa; 209 | 210 | break; 211 | } 212 | case OCModType: 213 | { 214 | objc1_32_module ocMod = *(objc1_32_module*)inObject; 215 | 216 | theValue = ocMod.name; 217 | 218 | break; 219 | } 220 | case OCGenericType: 221 | theValue = *(uint32_t*)inObject; 222 | 223 | break; 224 | 225 | default: 226 | return NO; 227 | break; 228 | } 229 | 230 | if (iSwapped) 231 | theValue = OSSwapInt32(theValue); 232 | 233 | *outDescription = [self getPointer:theValue type:NULL]; 234 | 235 | return (*outDescription != NULL); 236 | } 237 | 238 | // getObjc1Symtab:defs:fromModule: (was get_symtab) 239 | // ---------------------------------------------------------------------------- 240 | // Removed the truncation flag. 'left' is no longer used by the caller. 241 | 242 | - (BOOL)getObjc1Symtab: (objc1_32_symtab*)outSymTab 243 | defs: (uint32_t **)outDefs 244 | fromModule: (objc1_32_module*)inModule; 245 | { 246 | if (!outSymTab) 247 | return NO; 248 | 249 | uint32_t addr = inModule->symtab; 250 | uint32_t i, left; 251 | 252 | *outSymTab = (objc1_32_symtab){0}; 253 | 254 | for (i = 0; i < iNumObjcSects; i++) 255 | { 256 | if (addr >= iObjcSects[i].s.addr && 257 | addr < iObjcSects[i].s.addr + iObjcSects[i].size) 258 | { 259 | left = iObjcSects[i].size - 260 | (addr - iObjcSects[i].s.addr); 261 | 262 | if (left >= sizeof(objc1_32_symtab) - sizeof(uint32_t)) 263 | { 264 | memcpy(outSymTab, iObjcSects[i].contents + 265 | (addr - iObjcSects[i].s.addr), 266 | sizeof(objc1_32_symtab) - sizeof(uint32_t)); 267 | *outDefs = (uint32_t *)(iObjcSects[i].contents + 268 | (addr - iObjcSects[i].s.addr) + 269 | sizeof(objc1_32_symtab) - sizeof(uint32_t)); 270 | } 271 | else 272 | { 273 | memcpy(outSymTab, iObjcSects[i].contents + 274 | (addr - iObjcSects[i].s.addr), left); 275 | *outDefs = NULL; 276 | } 277 | 278 | return YES; 279 | } 280 | } 281 | 282 | return NO; 283 | } 284 | 285 | // getObjc1Class:fromDef: (was get_objc_class) 286 | // ---------------------------------------------------------------------------- 287 | 288 | - (BOOL)getObjc1Class: (objc1_32_class*)outClass 289 | fromDef: (uint32_t)inDef; 290 | { 291 | if (iObjcVersion < 2) 292 | { 293 | uint32_t i; 294 | 295 | for (i = 0; i < iNumObjcSects; i++) 296 | { 297 | if (inDef >= iObjcSects[i].s.addr && 298 | inDef < iObjcSects[i].s.addr + iObjcSects[i].size) 299 | { 300 | *outClass = *(objc1_32_class*)(iObjcSects[i].contents + 301 | (inDef - iObjcSects[i].s.addr)); 302 | 303 | return YES; 304 | } 305 | } 306 | } 307 | 308 | return NO; 309 | } 310 | 311 | // getObjc1Category:fromDef: (was get_objc_category) 312 | // ---------------------------------------------------------------------------- 313 | 314 | - (BOOL)getObjc1Category: (objc1_32_category*)outCat 315 | fromDef: (uint32_t)inDef; 316 | { 317 | if (iObjcVersion < 2) 318 | { 319 | uint32_t i; 320 | 321 | for (i = 0; i < iNumObjcSects; i++) 322 | { 323 | if (inDef >= iObjcSects[i].s.addr && 324 | inDef < iObjcSects[i].s.addr + iObjcSects[i].s.size) 325 | { 326 | *outCat = *(objc1_32_category*)(iObjcSects[i].contents + 327 | (inDef - iObjcSects[i].s.addr)); 328 | 329 | return YES; 330 | } 331 | } 332 | } 333 | 334 | return NO; 335 | } 336 | 337 | // getObjc1Class:fromName: 338 | // ---------------------------------------------------------------------------- 339 | // Given a class name, return the class itself. This func is used to tie 340 | // categories to classes. We have 2 pointers to the same name, so pointer 341 | // equality is sufficient. 342 | 343 | - (BOOL)getObjc1Class: (objc1_32_class *)outClass 344 | fromName: (const char*)inName; 345 | { 346 | uint32_t i, namePtr; 347 | 348 | for (i = 0; i < iNumClassMethodInfos; i++) 349 | { 350 | namePtr = (uint32_t)iClassMethodInfos[i].oc_class.name; 351 | 352 | if (iSwapped) 353 | namePtr = OSSwapInt32(namePtr); 354 | 355 | if ([self getPointer:namePtr type:NULL] == inName) 356 | { 357 | *outClass = iClassMethodInfos[i].oc_class; 358 | return YES; 359 | } 360 | } 361 | 362 | *outClass = (objc1_32_class){0}; 363 | 364 | return NO; 365 | } 366 | 367 | // getObjc1MetaClass:fromClass: 368 | // ---------------------------------------------------------------------------- 369 | 370 | - (BOOL)getObjc1MetaClass: (objc1_32_class*)outClass 371 | fromClass: (objc1_32_class*)inClass; 372 | { 373 | if (iObjcVersion < 2) 374 | { 375 | if (inClass->isa >= iMetaClassSect.s.addr && 376 | inClass->isa < iMetaClassSect.s.addr + iMetaClassSect.s.size) 377 | { 378 | *outClass = *(objc1_32_class*)(iMetaClassSect.contents + 379 | (inClass->isa - iMetaClassSect.s.addr)); 380 | 381 | return YES; 382 | } 383 | } 384 | 385 | return NO; 386 | } 387 | 388 | @end 389 | -------------------------------------------------------------------------------- /src/source/ObjcTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | ObjcTypes.h 3 | 4 | Definitions shared by GUI and CLI targets. 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | 10 | #import 11 | 12 | #pragma mark - 13 | #pragma mark Shared (32-bit) 14 | 15 | typedef struct { 16 | uint32_t isa; /* Class */ 17 | uint32_t superclass; /* Class */ 18 | } *objc_32_class_ptr; 19 | 20 | 21 | #pragma mark - 22 | #pragma mark Objective-C 1.0 (32-bit) 23 | 24 | typedef struct { 25 | uint32_t isa; /* Class */ 26 | uint32_t super_class; /* Class */ 27 | uint32_t name; /* const char * */ 28 | int32_t version; /* long */ 29 | int32_t info; /* long */ 30 | int32_t instance_size; /* long */ 31 | uint32_t ivars; /* struct objc_ivar_list * */ 32 | uint32_t methodLists; /* struct objc_method_list ** */ 33 | uint32_t cache; /* struct objc_cache * */ 34 | uint32_t protocols; /* struct objc_protocol_list * */ 35 | } objc1_32_class; 36 | 37 | 38 | typedef struct { 39 | uint32_t category_name; /* char * */ 40 | uint32_t class_name; /* char * */ 41 | uint32_t instance_methods; /* struct objc_method_list * */ 42 | uint32_t class_methods; /* struct objc_method_list * */ 43 | uint32_t protocols; /* struct objc_protocol_list * */ 44 | } objc1_32_category; 45 | 46 | 47 | typedef struct { 48 | uint32_t next; /* struct objc_protocol_list * */ 49 | uint32_t count; /* long */ 50 | uint32_t list[1]; /* Protocol * */ 51 | } objc1_32_protocol_list; 52 | 53 | 54 | typedef struct { 55 | uint32_t name; /* const char * */ 56 | uint32_t value; /* const char * */ 57 | } objc1_32_property_attribute_t; 58 | 59 | 60 | typedef struct { 61 | uint32_t ivar_name; /* char * */ 62 | uint32_t ivar_type; /* char * */ 63 | uint32_t ivar_offset; 64 | } objc1_32_ivar; 65 | 66 | 67 | typedef struct { 68 | int32_t ivar_count; /* int */ 69 | objc1_32_ivar ivar_list[1]; /* variable length structure */ 70 | } objc1_32_ivar_list; 71 | 72 | 73 | typedef struct { 74 | uint32_t method_name; /* SEL */ 75 | uint32_t method_types; /* char * */ 76 | uint32_t method_imp; /* IMP */ 77 | } objc1_32_method; 78 | 79 | 80 | typedef struct { 81 | int32_t obsolete; /* struct objc_method_list * */ 82 | int32_t method_count; /* int */ 83 | objc1_32_method method_list[1]; /* variable length structure */ 84 | } objc1_32_method_list; 85 | 86 | 87 | typedef struct { 88 | uint32_t name; /* SEL */ 89 | uint32_t *types; /* char * */ 90 | } objc1_32_method_description; 91 | 92 | 93 | typedef struct { 94 | uint32_t version; /* unsigned long */ 95 | uint32_t size; /* unsigned long */ 96 | uint32_t name; /* const char * */ 97 | uint32_t symtab; /* objc_symtab * */ 98 | } objc1_32_module; 99 | 100 | 101 | typedef struct { 102 | uint32_t sel_ref_cnt; /* unsigned long */ 103 | uint32_t refs; /* SEL * */ 104 | uint16_t cls_def_cnt; /* unsigned short */ 105 | uint16_t cat_def_cnt; /* unsigned short */ 106 | uint32_t defs[1]; /* void *, variable size */ 107 | } objc1_32_symtab; 108 | 109 | 110 | typedef struct { 111 | uint32_t mask; /* unsigned int, total = mask + 1 */ 112 | uint32_t occupied; /* unsigned int */ 113 | uint32_t buckets[1]; /* Method */ 114 | } objc1_32_cache; 115 | 116 | 117 | void swap_objc1_32_module(objc1_32_module *module); 118 | void swap_objc1_32_symtab(objc1_32_symtab *symtab); 119 | void swap_objc1_32_class(objc1_32_class *cls); 120 | void swap_objc1_32_ivar(objc1_32_ivar *ivar); 121 | void swap_objc1_32_category(objc1_32_category *category); 122 | void swap_objc1_32_method_list(objc1_32_method_list *methodList); 123 | void swap_objc1_32_method(objc1_32_method *method); 124 | 125 | 126 | #pragma mark - 127 | #pragma mark Objective-C 1.0 (64-bit) 128 | 129 | typedef struct { 130 | uint64_t isa; /* Class */ 131 | uint64_t super_class; /* Class */ 132 | uint64_t name; /* const char * */ 133 | int64_t version; /* long */ 134 | int64_t info; /* long */ 135 | int64_t instance_size; /* long */ 136 | uint64_t ivars; /* struct objc_ivar_list * */ 137 | uint64_t methodLists; /* struct objc_method_list ** */ 138 | uint64_t cache; /* struct objc_cache * */ 139 | uint64_t protocols; /* struct objc_protocol_list * */ 140 | } objc1_64_class; 141 | 142 | 143 | typedef struct { 144 | uint64_t category_name; /* char * */ 145 | uint64_t class_name; /* char * */ 146 | uint64_t instance_methods; /* struct objc_method_list * */ 147 | uint64_t class_methods; /* struct objc_method_list * */ 148 | uint64_t protocols; /* struct objc_protocol_list * */ 149 | } objc1_64_category; 150 | 151 | 152 | typedef struct { 153 | uint64_t next; /* struct objc_protocol_list * */ 154 | uint64_t count; /* long */ 155 | uint64_t list[1]; /* Protocol * */ 156 | } objc1_64_protocol_list; 157 | 158 | 159 | typedef struct { 160 | uint64_t name; /* const char * */ 161 | uint64_t value; /* const char * */ 162 | } objc1_64_property_attribute_t; 163 | 164 | 165 | typedef struct { 166 | uint64_t ivar_name; /* char * */ 167 | uint64_t ivar_type; /* char * */ 168 | uint64_t ivar_offset; 169 | uint32_t space; 170 | } objc1_64_ivar; 171 | 172 | 173 | typedef struct { 174 | int32_t ivar_count; /* int */ 175 | int32_t space; /* int */ 176 | objc1_64_ivar ivar_list[1]; /* variable length structure */ 177 | } objc1_64_ivar_list; 178 | 179 | 180 | typedef struct { 181 | uint64_t method_name; /* SEL */ 182 | uint64_t method_types; /* char * */ 183 | uint64_t method_imp; /* IMP */ 184 | } objc1_64_method; 185 | 186 | 187 | typedef struct { 188 | int64_t obsolete; /* struct objc_method_list * */ 189 | int64_t method_count; /* int */ 190 | int32_t space; /* int */ 191 | objc1_64_method method_list[1]; /* variable length structure */ 192 | } objc1_64_method_list; 193 | 194 | 195 | typedef struct { 196 | uint64_t name; /* SEL */ 197 | uint64_t *types; /* char * */ 198 | } objc1_64_method_description; 199 | 200 | 201 | typedef struct { 202 | uint64_t version; /* unsigned long */ 203 | uint64_t size; /* unsigned long */ 204 | uint64_t name; /* const char * */ 205 | uint64_t symtab; /* objc_symtab * */ 206 | } objc1_64_module; 207 | 208 | 209 | typedef struct { 210 | uint64_t sel_ref_cnt; /* unsigned long */ 211 | uint64_t refs; /* SEL * */ 212 | uint16_t cls_def_cnt; /* unsigned short */ 213 | uint16_t cat_def_cnt; /* unsigned short */ 214 | uint64_t defs[1]; /* void *, variable size */ 215 | } objc1_64_symtab; 216 | 217 | 218 | typedef struct { 219 | uint32_t mask; /* unsigned int, total = mask + 1 */ 220 | uint32_t occupied; /* unsigned int */ 221 | uint64_t buckets[1]; /* Method */ 222 | } objc1_64_cache; 223 | 224 | 225 | void swap_objc1_64_module(objc1_64_module *module); 226 | void swap_objc1_64_symtab(objc1_64_symtab *symtab); 227 | void swap_objc1_64_class(objc1_64_class *cls); 228 | void swap_objc1_64_ivar(objc1_64_ivar *ivar); 229 | void swap_objc1_64_category(objc1_64_category *category); 230 | void swap_objc1_64_method_list(objc1_64_method_list *methodList); 231 | void swap_objc1_64_method(objc1_64_method *method); 232 | 233 | 234 | /* ---------------------------------------------------------------------------- 235 | Objective-C 2.0 private structs 236 | 237 | Copied and modified here because- 238 | The structs are private, unlike the earlier runtime. 239 | otx being 32-bit, the pointer fields need to be explicit about their size. 240 | 241 | For reference, the 'FOO' in 'typedef struct FOO' is the original private struct 242 | name, and the original pointer field types are saved as comments. 243 | */ 244 | 245 | 246 | #pragma mark - 247 | #pragma mark Objective-C 2.0 (32-bit) 248 | 249 | typedef struct { 250 | uint32_t name; // SEL 251 | uint32_t types; // const char * 252 | uint32_t imp; // IMP 253 | } objc2_32_method_t; 254 | 255 | 256 | typedef struct { 257 | uint32_t entsize; 258 | uint32_t count; 259 | objc2_32_method_t first; 260 | } objc2_32_method_list_t; 261 | 262 | 263 | typedef struct { 264 | uint32_t imp; // IMP 265 | uint32_t sel; // SEL 266 | } objc2_32_message_ref_t; 267 | 268 | 269 | typedef struct { 270 | // *offset is 64-bit by accident even though other 271 | // fields restrict total instance size to 32-bit. 272 | uint64_t offset; // uintptr_t * 273 | uint32_t name; // const char * 274 | uint32_t type; // const char * 275 | uint32_t alignment; 276 | uint32_t size; 277 | } objc2_32_ivar_t; 278 | 279 | 280 | typedef struct { 281 | uint32_t entsize; 282 | uint32_t count; 283 | objc2_32_ivar_t first; 284 | } objc2_32_ivar_list_t; 285 | 286 | 287 | typedef struct { 288 | uint32_t isa; // id 289 | uint32_t name; // const char * 290 | uint32_t protocols; // struct objc2_protocol_list_t * 291 | uint32_t instanceMethods; // objc2_method_list_t * 292 | uint32_t classMethods; // objc2_method_list_t * 293 | uint32_t optionalInstanceMethods; // objc2_method_list_t * 294 | uint32_t optionalClassMethods; // objc2_method_list_t * 295 | uint32_t instanceProperties; // struct objc2_property_list * 296 | } objc2_32_protocol_t; 297 | 298 | 299 | typedef struct { 300 | // count is 64-bit by accident. 301 | uint64_t count; // uintptr_t 302 | uint32_t list[0]; // objc2_protocol_t * 303 | } objc2_32_protocol_list_t; 304 | 305 | 306 | typedef struct { 307 | uint32_t flags; 308 | uint32_t instanceStart; 309 | uint32_t instanceSize; 310 | 311 | uint32_t ivarLayout; // const uint8_t * 312 | 313 | uint32_t name; // const char * 314 | uint32_t baseMethods; // const objc2_method_list_t * 315 | uint32_t baseProtocols; // const objc2_protocol_list_t * 316 | uint32_t ivars; // const objc2_ivar_list_t * 317 | 318 | uint32_t weakIvarLayout; // const uint8_t * 319 | uint32_t baseProperties; // const struct objc2_property_list * 320 | } objc2_32_class_ro_t; 321 | 322 | 323 | typedef struct { 324 | uint32_t flags; 325 | uint32_t version; 326 | 327 | uint32_t ro; // const objc2_class_ro_t * 328 | 329 | uint32_t methods; // chained_method_list * 330 | uint32_t properties; // chained_property_list * 331 | uint32_t protocols; // objc2_protocol_list_t ** 332 | 333 | uint32_t firstSubclass; // objc2_class_t * 334 | uint32_t nextSiblingClass; // objc2_class_t * 335 | } objc2_32_class_rw_t; 336 | 337 | 338 | typedef struct { 339 | uint32_t isa; // objc2_class_t * 340 | uint32_t superclass; // objc2_class_t * 341 | uint32_t cache; // Cache 342 | uint32_t vtable; // IMP * 343 | uint32_t data; // objc2_class_rw_t * 344 | } objc2_32_class_t; 345 | 346 | 347 | extern void swap_objc2_32_class(objc2_32_class_t *cls); 348 | extern void swap_objc2_32_method(objc2_32_method_t *method); 349 | extern void swap_objc2_32_ivar(objc2_32_ivar_t* ivar); 350 | 351 | 352 | #pragma mark - 353 | #pragma mark Objective-C 2.0 (64-bit) 354 | 355 | typedef struct { 356 | uint64_t name; // SEL 357 | uint64_t types; // const char * 358 | uint64_t imp; // IMP 359 | } objc2_64_method_t; 360 | 361 | 362 | typedef struct { 363 | uint32_t entsize; 364 | uint32_t count; 365 | objc2_64_method_t first; 366 | } objc2_64_method_list_t; 367 | 368 | 369 | typedef struct { 370 | uint64_t imp; // IMP 371 | uint64_t sel; // SEL 372 | } objc2_64_message_ref_t; 373 | 374 | 375 | typedef struct { 376 | // *offset is 64-bit by accident even though other 377 | // fields restrict total instance size to 32-bit. 378 | uint64_t offset; // uintptr_t * 379 | uint64_t name; // const char * 380 | uint64_t type; // const char * 381 | uint32_t alignment; 382 | uint32_t size; 383 | } objc2_64_ivar_t; 384 | 385 | 386 | typedef struct { 387 | uint32_t entsize; 388 | uint32_t count; 389 | objc2_64_ivar_t first; 390 | } objc2_64_ivar_list_t; 391 | 392 | 393 | typedef struct { 394 | uint64_t isa; // id 395 | uint64_t name; // const char * 396 | uint64_t protocols; // struct objc2_protocol_list_t * 397 | uint64_t instanceMethods; // objc2_method_list_t * 398 | uint64_t classMethods; // objc2_method_list_t * 399 | uint64_t optionalInstanceMethods; // objc2_method_list_t * 400 | uint64_t optionalClassMethods; // objc2_method_list_t * 401 | uint64_t instanceProperties; // struct objc2_property_list * 402 | } objc2_64_protocol_t; 403 | 404 | 405 | typedef struct { 406 | uint64_t count; // uintptr_t - count is 64-bit by accident. 407 | uint64_t list[0]; // objc2_protocol_t * 408 | } objc2_64_protocol_list_t; 409 | 410 | 411 | typedef struct { 412 | uint32_t flags; 413 | uint32_t instanceStart; 414 | uint32_t instanceSize; 415 | uint32_t reserved; 416 | 417 | uint64_t ivarLayout; // const uint8_t * 418 | 419 | uint64_t name; // const char * 420 | uint64_t baseMethods; // const objc2_method_list_t * 421 | uint64_t baseProtocols; // const objc2_protocol_list_t * 422 | uint64_t ivars; // const objc2_ivar_list_t * 423 | 424 | uint64_t weakIvarLayout; // const uint8_t * 425 | uint64_t baseProperties; // const struct objc2_property_list * 426 | } objc2_64_class_ro_t; 427 | 428 | 429 | typedef struct { 430 | uint32_t flags; 431 | uint32_t version; 432 | 433 | uint64_t ro; // const objc2_class_ro_t * 434 | 435 | uint64_t methods; // chained_method_list * 436 | uint64_t properties; // chained_property_list * 437 | uint64_t protocols; // objc2_protocol_list_t ** 438 | 439 | uint64_t firstSubclass; // objc2_class_t * 440 | uint64_t nextSiblingClass; // objc2_class_t * 441 | } objc2_64_class_rw_t; 442 | 443 | 444 | typedef struct { 445 | uint64_t isa; // objc2_class_t * 446 | uint64_t superclass; // objc2_class_t * 447 | uint64_t cache; // Cache 448 | uint64_t vtable; // IMP * 449 | uint64_t data; // objc2_class_rw_t * 450 | } objc2_64_class_t; 451 | 452 | extern void swap_objc2_64_class(objc2_64_class_t *cls); 453 | extern void swap_objc2_64_method(objc2_64_method_t *method); 454 | extern void swap_objc2_64_ivar(objc2_64_ivar_t *ivar); 455 | 456 | -------------------------------------------------------------------------------- /src/source/SyscallStrings.h: -------------------------------------------------------------------------------- 1 | /* 2 | SyscallStrings.h 3 | 4 | Adapted from . 5 | 6 | This file is in the public domain. 7 | */ 8 | 9 | // Using 0 instead of "" for empty strings results in a nil pointer 10 | // instead of a pointer to zeroes. 11 | 12 | static const char* gSysCalls[371] = { 13 | "syscall", // 0 14 | "exit", // 1 15 | "fork", // 2 16 | "read", // 3 17 | "write", // 4 18 | "open", // 5 19 | "close", // 6 20 | "wait4", // 7 21 | 0, // 8 22 | "link", // 9 23 | "unlink", // 10 24 | 0, // 11 25 | "chdir", // 12 26 | "fchdir", // 13 27 | "mknod", // 14 28 | "chmod", // 15 29 | "chown", // 16 30 | "obreak", // 17 31 | "getfsstat", // 18 32 | 0, // 19 33 | "getpid", // 20 34 | 0,0, // 21, 2 35 | "setuid", // 23 36 | "getuid", // 24 37 | "geteuid", // 25 38 | "ptrace", // 26 39 | "recvmsg", // 27 40 | "sendmsg", // 28 41 | "recvfrom", // 29 42 | "accept", // 30 43 | "getpeername", // 31 44 | "getsockname", // 32 45 | "access", // 33 46 | "chflags", // 34 47 | "fchflags", // 35 48 | "sync", // 36 49 | "kill", // 37 50 | 0, // 38 51 | "getppid", // 39 52 | 0, // 40 53 | "dup", // 41 54 | "pipe", // 42 55 | "getegid", // 43 56 | "profil", // 44 57 | "ktrace", // 45 58 | "sigaction", // 46 59 | "getgid", // 47 60 | "sigprocmask", // 48 61 | "getlogin", // 49 62 | "setlogin", // 50 63 | "acct", // 51 64 | "sigpending", // 52 65 | "sigaltstack", // 53 66 | "ioctl", // 54 67 | "reboot", // 55 68 | "revoke", // 56 69 | "symlink", // 57 70 | "readlink", // 58 71 | "execve", // 59 72 | "umask", // 60 73 | "chroot", // 61 74 | 0,0,0, // 62 - 64 75 | "msync", // 65 76 | "vfork", // 66 77 | 0,0, // 67, 8 78 | "sbrk", // 69 79 | "sstk", // 70 80 | 0, // 71 81 | "ovadvise", // 72 82 | "munmap", // 73 83 | "mprotect", // 74 84 | "madvise", // 75 85 | 0,0, // 76, 7 86 | "mincore", // 78 87 | "getgroups", // 79 88 | "setgroups", // 80 89 | "getpgrp", // 81 90 | "setpgid", // 82 91 | "setitimer", // 83 92 | 0, // 84 93 | "swapon", // 85 94 | "getitimer", // 86 95 | 0,0, // 87, 8 96 | "getdtablesize", // 89 97 | "dup2", // 90 98 | 0, // 91 99 | "fcntl", // 92 100 | "select", // 93 101 | 0, // 94 102 | "fsync", // 95 103 | "setpriority", // 96 104 | "socket", // 97 105 | "connect", // 98 106 | 0, // 99 107 | "getpriority", // 100 108 | 0,0,0, // 101 - 103 109 | "bind", // 104 110 | "setsockopt", // 105 111 | "listen", // 106 112 | 0,0,0,0, // 107 - 110 113 | "sigsuspend", // 111 114 | 0,0,0,0, // 112 - 115 115 | "gettimeofday", // 116 116 | "getrusage", // 117 117 | "getsockopt", // 118 118 | 0, // 119 119 | "readv", // 120 120 | "writev", // 121 121 | "settimeofday", // 122 122 | "fchown", // 123 123 | "fchmod", // 124 124 | 0,0,0, // 125 - 127 125 | "rename", // 128 126 | 0,0, // 129, 130 127 | "flock", // 131 128 | "mkfifo", // 132 129 | "sendto", // 133 130 | "shutdown", // 134 131 | "socketpair", // 135 132 | "mkdir", // 136 133 | "rmdir", // 137 134 | "utimes", // 138 135 | "futimes", // 139 136 | "adjtime", // 140 137 | 0,0,0,0,0,0, // 141 - 146 138 | "setsid", // 147 139 | 0,0,0, // 148 - 150 140 | "getpgid", // 151 141 | "setprivexec", // 152 142 | "pread", // 153 143 | "pwrite", // 154 144 | "nfssvc", // 155 145 | 0, // 156 146 | "statfs", // 157 147 | "fstatfs", // 158 148 | "unmount", // 159 149 | 0, // 160 150 | "getfh", // 161 151 | 0,0,0, // 162 - 164 152 | "quotactl", // 165 153 | 0, // 166 154 | "mount", // 167 155 | 0,0, // 168, 9 156 | "table", // 170 157 | 0,0, // 171, 2 158 | "waitid", // 173 159 | 0,0, // 174, 5 160 | "add_profil", // 176 161 | 0,0,0, // 177 - 179 162 | "kdebug_trace", // 180 163 | "setgid", // 181 164 | "setegid", // 182 165 | "seteuid", // 183 166 | "sigreturn", // 184 167 | "chud", // 185 168 | 0,0, // 186, 7 169 | "stat", // 188 170 | "fstat", // 189 171 | "lstat", // 190 172 | "pathconf", // 191 173 | "fpathconf", // 192 174 | "getfsstat", // 193 175 | "getrlimit", // 194 176 | "setrlimit", // 195 177 | "getdirentries", // 196 178 | "mmap", // 197 179 | 0, // 198 180 | "lseek", // 199 181 | "truncate", // 200 182 | "ftruncate", // 201 183 | "__sysctl", // 202 184 | "mlock", // 203 185 | "munlock", // 204 186 | "undelete", // 205 187 | "ATsocket", // 206 188 | "ATgetmsg", // 207 189 | "ATputmsg", // 208 190 | "ATPsndreq", // 209 191 | "ATPsndrsp", // 210 192 | "ATPgetreq", // 211 193 | "ATPgetrsp", // 212 194 | 0, // 213 195 | "kqueue_from_portset_np", // 214 196 | "kqueue_portset_np", // 215 197 | "mkcomplex", // 216 198 | "statv", // 217 199 | "lstatv", // 218 200 | "fstatv", // 219 201 | "getattrlist", // 220 202 | "setattrlist", // 221 203 | "getdirentriesattr", // 222 204 | "exchangedata", // 223 205 | "checkuseraccess", // 224 206 | "searchfs", // 225 207 | "delete", // 226 208 | "copyfile", // 227 209 | 0,0, // 228, 9 210 | "poll", // 230 211 | "watchevent", // 231 212 | "waitevent", // 232 213 | "modwatch", // 233 214 | "getxattr", // 234 215 | "fgetxattr", // 235 216 | "setxattr", // 236 217 | "fsetxattr", // 237 218 | "removexattr", // 238 219 | "fremovexattr", // 239 220 | "listxattr", // 240 221 | "flistxattr", // 241 222 | "fsctl", // 242 223 | "initgroups", // 243 224 | 0,0,0, // 244 - 246 225 | "nfsclnt", // 247 226 | "fhopen", // 248 227 | 0, // 249 228 | "minherit", // 250 229 | "semsys", // 251 230 | "msgsys", // 252 231 | "shmsys", // 253 232 | "semctl", // 254 233 | "semget", // 255 234 | "semop", // 256 235 | "semconfig", // 257 236 | "msgctl", // 258 237 | "msgget", // 259 238 | "msgsnd", // 260 239 | "msgrcv", // 261 240 | "shmat", // 262 241 | "shmctl", // 263 242 | "shmdt", // 264 243 | "shmget", // 265 244 | "shm_open", // 266 245 | "shm_unlink", // 267 246 | "sem_open", // 268 247 | "sem_close", // 269 248 | "sem_unlink", // 270 249 | "sem_wait", // 271 250 | "sem_trywait", // 272 251 | "sem_post", // 273 252 | "sem_getvalue", // 274 253 | "sem_init", // 275 254 | "sem_destroy", // 276 255 | "open_extended", // 277 256 | "umask_extended", // 278 257 | "stat_extended", // 279 258 | "lstat_extended", // 280 259 | "fstat_extended", // 281 260 | "chmod_extended", // 282 261 | "fchmod_extended", // 283 262 | "access_extended", // 284 263 | "settid", // 285 264 | "gettid", // 286 265 | "setsgroups", // 287 266 | "getsgroups", // 288 267 | "setwgroups", // 289 268 | "getwgroups", // 290 269 | "mkfifo_extended", // 291 270 | "mkdir_extended", // 292 271 | "identitysvc", // 293 272 | 0,0, // 294, 5 273 | "load_shared_file", // 296 274 | "reset_shared_file", // 297 275 | "new_system_shared_regions", // 298 276 | "shared_region_map_file_np", // 299 277 | "shared_region_make_private_np", // 300 278 | 0,0,0,0,0,0,0,0,0, // 301 - 309 279 | "getsid", // 310 280 | "settid_with_pid", // 311 281 | 0, // 312 282 | "aio_fsync", // 313 283 | "aio_return", // 314 284 | "aio_suspend", // 315 285 | "aio_cancel", // 316 286 | "aio_error", // 317 287 | "aio_read", // 318 288 | "aio_write", // 319 289 | "lio_listio", // 320 290 | 0,0,0, // 321 - 323 291 | "mlockall", // 324 292 | "munlockall", // 325 293 | 0, // 326 294 | "issetugid", // 327 295 | "__pthread_kill", // 328 296 | "pthread_sigmask", // 329 297 | "sigwait", // 330 298 | "__disable_threadsignal", // 331 299 | "__pthread_markcancel", // 332 300 | "__pthread_canceled", // 333 301 | "__semwait_signal", // 334 302 | "utrace", // 335 303 | "proc_info", // 336 304 | 0,0,0,0,0,0,0,0,0,0,0,0,0, // 337 - 349 305 | "audit", // 350 306 | "auditon", // 351 307 | 0, // 352 308 | "getauid", // 353 309 | "setauid", // 354 310 | "getaudit", // 355 311 | "setaudit", // 356 312 | "getaudit_addr", // 357 313 | "setaudit_addr", // 358 314 | "auditctl", // 359 315 | 0,0, // 361, 2 316 | "kqueue", // 362 317 | "kevent", // 363 318 | "lchown", // 364 319 | "stack_snapshot", // 365 320 | 0,0,0,0, // 366 - 369 321 | "MAXSYSCALL" // 370 322 | }; 323 | --------------------------------------------------------------------------------