-
Notifications
You must be signed in to change notification settings - Fork 28
/
CDLoadCommand.m
232 lines (201 loc) · 9.53 KB
/
CDLoadCommand.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// -*- mode: ObjC -*-
// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-2019 Steve Nygard.
#import "CDLoadCommand.h"
#import "CDLCBuildVersion.h"
#import "CDLCDyldInfo.h"
#import "CDLCDylib.h"
#import "CDLCDylinker.h"
#import "CDLCDynamicSymbolTable.h"
#import "CDLCEncryptionInfo.h"
#import "CDLCFunctionStarts.h"
#import "CDLCLinkeditData.h"
#import "CDLCPrebindChecksum.h"
#import "CDLCPreboundDylib.h"
#import "CDLCRoutines32.h"
#import "CDLCRoutines64.h"
#import "CDLCRunPath.h"
#import "CDLCSegment.h"
#import "CDLCSubClient.h"
#import "CDLCSubFramework.h"
#import "CDLCSubLibrary.h"
#import "CDLCSubUmbrella.h"
#import "CDLCSymbolTable.h"
#import "CDLCTwoLevelHints.h"
#import "CDLCUnixThread.h"
#import "CDLCUUID.h"
#import "CDLCUnknown.h"
#import "CDLCVersionMinimum.h"
#import "CDMachOFile.h"
#import "CDLCMain.h"
#import "CDLCDataInCode.h"
#import "CDLCSourceVersion.h"
@implementation CDLoadCommand
{
__weak CDMachOFile *_machOFile;
NSUInteger _commandOffset;
}
+ (id)loadCommandWithDataCursor:(CDMachOFileDataCursor *)cursor;
{
Class targetClass = [CDLCUnknown class];
uint32_t val = [cursor peekInt32];
switch (val) {
case LC_SEGMENT: targetClass = [CDLCSegment class]; break;
case LC_SEGMENT_64: targetClass = [CDLCSegment class]; break;
case LC_SYMTAB: targetClass = [CDLCSymbolTable class]; break;
//case LC_SYMSEG: // obsolete
//case LC_THREAD: // not used?
case LC_UNIXTHREAD: targetClass = [CDLCUnixThread class]; break;
//case LC_LOADFVMLIB: // not used?
//case LC_IDFVMLIB: // not used?
//case LC_IDENT: // not used?
//case LC_FVMFILE: // not used?
//case LC_PREPAGE: // not used
case LC_DYSYMTAB: targetClass = [CDLCDynamicSymbolTable class]; break;
case LC_LOAD_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_ID_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_LOAD_DYLINKER: targetClass = [CDLCDylinker class]; break;
case LC_ID_DYLINKER: targetClass = [CDLCDylinker class]; break;
case LC_PREBOUND_DYLIB: targetClass = [CDLCPreboundDylib class]; break;
case LC_ROUTINES: targetClass = [CDLCRoutines32 class]; break;
case LC_SUB_FRAMEWORK: targetClass = [CDLCSubFramework class]; break;
//case LC_SUB_UMBRELLA: targetClass = [CDLCSubUmbrella class]; break;
case LC_SUB_CLIENT: targetClass = [CDLCSubClient class]; break;
//case LC_SUB_LIBRARY: targetClass = [CDLCSubLibrary class]; break;
case LC_TWOLEVEL_HINTS: targetClass = [CDLCTwoLevelHints class]; break;
case LC_PREBIND_CKSUM: targetClass = [CDLCPrebindChecksum class]; break;
case LC_LOAD_WEAK_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_ROUTINES_64: targetClass = [CDLCRoutines64 class]; break;
case LC_UUID: targetClass = [CDLCUUID class]; break;
case LC_RPATH: targetClass = [CDLCRunPath class]; break;
case LC_CODE_SIGNATURE: targetClass = [CDLCLinkeditData class]; break;
case LC_SEGMENT_SPLIT_INFO: targetClass = [CDLCLinkeditData class]; break;
case LC_REEXPORT_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_LAZY_LOAD_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_ENCRYPTION_INFO:
case LC_ENCRYPTION_INFO_64: targetClass = [CDLCEncryptionInfo class]; break;
case LC_DYLD_INFO: targetClass = [CDLCDyldInfo class]; break;
case LC_DYLD_INFO_ONLY: targetClass = [CDLCDyldInfo class]; break;
case LC_LOAD_UPWARD_DYLIB: targetClass = [CDLCDylib class]; break;
case LC_VERSION_MIN_MACOSX: targetClass = [CDLCVersionMinimum class]; break;
case LC_VERSION_MIN_IPHONEOS: targetClass = [CDLCVersionMinimum class]; break;
case LC_FUNCTION_STARTS: targetClass = [CDLCFunctionStarts class]; break;
case LC_DYLD_ENVIRONMENT: targetClass = [CDLCDylinker class]; break;
case LC_MAIN: targetClass = [CDLCMain class]; break;
case LC_DATA_IN_CODE: targetClass = [CDLCDataInCode class]; break;
case LC_SOURCE_VERSION: targetClass = [CDLCSourceVersion class]; break;
case LC_DYLIB_CODE_SIGN_DRS: targetClass = [CDLCLinkeditData class]; break; // Designated Requirements
case LC_BUILD_VERSION: targetClass = [CDLCBuildVersion class]; break;
case LC_LINKER_OPTION:
case LC_LINKER_OPTIMIZATION_HINT:
case LC_VERSION_MIN_TVOS:
case LC_VERSION_MIN_WATCHOS:
case LC_NOTE:
default:
NSLog(@"Unknown load command: 0x%08x", val);
};
//NSLog(@"targetClass: %@", NSStringFromClass(targetClass));
return [[targetClass alloc] initWithDataCursor:cursor];
}
- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
{
if ((self = [super init])) {
_machOFile = [cursor machOFile];
_commandOffset = [cursor offset];
}
return self;
}
#pragma mark - Debugging
- (NSString *)description;
{
return [NSString stringWithFormat:@"<%@:%p> cmd: 0x%08x (%@), cmdsize: %d // %@",
NSStringFromClass([self class]), self,
self.cmd, self.commandName, self.cmdsize, [self extraDescription]];
}
- (NSString *)extraDescription;
{
return @"";
}
#pragma mark -
- (uint32_t)cmd;
{
// Implement in subclasses
[NSException raise:NSGenericException format:@"Must implement method in subclasses."];
return 0;
}
- (uint32_t)cmdsize;
{
// Implement in subclasses
[NSException raise:NSGenericException format:@"Must implement method in subclasses."];
return 0;
}
- (BOOL)mustUnderstandToExecute;
{
return (self.cmd & LC_REQ_DYLD) != 0;
}
- (NSString *)commandName;
{
switch (self.cmd) {
case LC_SEGMENT: return @"LC_SEGMENT";
case LC_SYMTAB: return @"LC_SYMTAB";
case LC_SYMSEG: return @"LC_SYMSEG";
case LC_THREAD: return @"LC_THREAD";
case LC_UNIXTHREAD: return @"LC_UNIXTHREAD";
case LC_LOADFVMLIB: return @"LC_LOADFVMLIB";
case LC_IDFVMLIB: return @"LC_IDFVMLIB";
case LC_IDENT: return @"LC_IDENT";
case LC_FVMFILE: return @"LC_FVMFILE";
case LC_PREPAGE: return @"LC_PREPAGE";
case LC_DYSYMTAB: return @"LC_DYSYMTAB";
case LC_LOAD_DYLIB: return @"LC_LOAD_DYLIB";
case LC_ID_DYLIB: return @"LC_ID_DYLIB";
case LC_LOAD_DYLINKER: return @"LC_LOAD_DYLINKER";
case LC_ID_DYLINKER: return @"LC_ID_DYLINKER";
case LC_PREBOUND_DYLIB: return @"LC_PREBOUND_DYLIB";
case LC_ROUTINES: return @"LC_ROUTINES";
case LC_SUB_FRAMEWORK: return @"LC_SUB_FRAMEWORK";
case LC_SUB_UMBRELLA: return @"LC_SUB_UMBRELLA";
case LC_SUB_CLIENT: return @"LC_SUB_CLIENT";
case LC_SUB_LIBRARY: return @"LC_SUB_LIBRARY";
case LC_TWOLEVEL_HINTS: return @"LC_TWOLEVEL_HINTS";
case LC_PREBIND_CKSUM: return @"LC_PREBIND_CKSUM";
case LC_LOAD_WEAK_DYLIB: return @"LC_LOAD_WEAK_DYLIB";
case LC_SEGMENT_64: return @"LC_SEGMENT_64";
case LC_ROUTINES_64: return @"LC_ROUTINES_64";
case LC_UUID: return @"LC_UUID";
case LC_RPATH: return @"LC_RPATH";
case LC_CODE_SIGNATURE: return @"LC_CODE_SIGNATURE";
case LC_SEGMENT_SPLIT_INFO: return @"LC_SEGMENT_SPLIT_INFO";
case LC_REEXPORT_DYLIB: return @"LC_REEXPORT_DYLIB";
case LC_LAZY_LOAD_DYLIB: return @"LC_LAZY_LOAD_DYLIB";
case LC_ENCRYPTION_INFO: return @"LC_ENCRYPTION_INFO";
case LC_DYLD_INFO: return @"LC_DYLD_INFO";
case LC_DYLD_INFO_ONLY: return @"LC_DYLD_INFO_ONLY";
case LC_LOAD_UPWARD_DYLIB: return @"LC_LOAD_UPWARD_DYLIB";
case LC_VERSION_MIN_MACOSX: return @"LC_VERSION_MIN_MACOSX";
case LC_VERSION_MIN_IPHONEOS: return @"LC_VERSION_MIN_IPHONEOS";
case LC_FUNCTION_STARTS: return @"LC_FUNCTION_STARTS";
case LC_DYLD_ENVIRONMENT: return @"LC_DYLD_ENVIRONMENT";
case LC_LINKER_OPTION: return @"LC_LINKER_OPTION";
case LC_LINKER_OPTIMIZATION_HINT: return @"LC_LINKER_OPTIMIZATION_HINT";
case LC_VERSION_MIN_TVOS: return @"LC_VERSION_MIN_TVOS";
case LC_VERSION_MIN_WATCHOS: return @"LC_VERSION_MIN_WATCHOS";
case LC_NOTE: return @"LC_NOTE";
case LC_BUILD_VERSION: return @"LC_BUILD_VERSION";
default:
break;
}
return [NSString stringWithFormat:@"0x%08x", [self cmd]];
}
- (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose;
{
[resultString appendFormat:@" cmd %@", [self commandName]];
if (self.mustUnderstandToExecute)
[resultString appendFormat:@" (must understand to execute)"];
[resultString appendFormat:@"\n"];
[resultString appendFormat:@" cmdsize %u\n", [self cmdsize]];
}
- (void)machOFileDidReadLoadCommands:(CDMachOFile *)machOFile;
{
}
@end