Add placeholder for types that start with A, for _Atomic() types.
[class-dump.git] / Source / CDLoadCommand.m
blob132991933b60fa2ea9acfac91e3e137c27e63534
1 // -*- mode: ObjC -*-
3 //  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
4 //  Copyright (C) 1997-2019 Steve Nygard.
6 #import "CDLoadCommand.h"
8 #import "CDLCBuildVersion.h"
9 #import "CDLCDyldInfo.h"
10 #import "CDLCDylib.h"
11 #import "CDLCDylinker.h"
12 #import "CDLCDynamicSymbolTable.h"
13 #import "CDLCEncryptionInfo.h"
14 #import "CDLCFunctionStarts.h"
15 #import "CDLCLinkeditData.h"
16 #import "CDLCPrebindChecksum.h"
17 #import "CDLCPreboundDylib.h"
18 #import "CDLCRoutines32.h"
19 #import "CDLCRoutines64.h"
20 #import "CDLCRunPath.h"
21 #import "CDLCSegment.h"
22 #import "CDLCSubClient.h"
23 #import "CDLCSubFramework.h"
24 #import "CDLCSubLibrary.h"
25 #import "CDLCSubUmbrella.h"
26 #import "CDLCSymbolTable.h"
27 #import "CDLCTwoLevelHints.h"
28 #import "CDLCUnixThread.h"
29 #import "CDLCUUID.h"
30 #import "CDLCUnknown.h"
31 #import "CDLCVersionMinimum.h"
32 #import "CDMachOFile.h"
34 #import "CDLCMain.h"
35 #import "CDLCDataInCode.h"
36 #import "CDLCSourceVersion.h"
38 @implementation CDLoadCommand
40     __weak CDMachOFile *_machOFile;
41     NSUInteger _commandOffset;
44 + (id)loadCommandWithDataCursor:(CDMachOFileDataCursor *)cursor;
46     Class targetClass = [CDLCUnknown class];
48     uint32_t val = [cursor peekInt32];
50     switch (val) {
51         case LC_SEGMENT:               targetClass = [CDLCSegment class]; break;
52         case LC_SEGMENT_64:            targetClass = [CDLCSegment class]; break;
53         case LC_SYMTAB:                targetClass = [CDLCSymbolTable class]; break;
54             //case LC_SYMSEG: // obsolete
55             //case LC_THREAD: // not used?
56         case LC_UNIXTHREAD:            targetClass = [CDLCUnixThread class]; break;
57             //case LC_LOADFVMLIB: // not used?
58             //case LC_IDFVMLIB: // not used?
59             //case LC_IDENT: // not used?
60             //case LC_FVMFILE: // not used?
61             //case LC_PREPAGE: // not used
62         case LC_DYSYMTAB:              targetClass = [CDLCDynamicSymbolTable class]; break;
63         case LC_LOAD_DYLIB:            targetClass = [CDLCDylib class]; break;
64         case LC_ID_DYLIB:              targetClass = [CDLCDylib class]; break;
65         case LC_LOAD_DYLINKER:         targetClass = [CDLCDylinker class]; break;
66         case LC_ID_DYLINKER:           targetClass = [CDLCDylinker class]; break;
67         case LC_PREBOUND_DYLIB:        targetClass = [CDLCPreboundDylib class]; break;
68         case LC_ROUTINES:              targetClass = [CDLCRoutines32 class]; break;
69         case LC_SUB_FRAMEWORK:         targetClass = [CDLCSubFramework class]; break;
70             //case LC_SUB_UMBRELLA:    targetClass = [CDLCSubUmbrella class]; break;
71         case LC_SUB_CLIENT:            targetClass = [CDLCSubClient class]; break;
72             //case LC_SUB_LIBRARY:     targetClass = [CDLCSubLibrary class]; break;
73         case LC_TWOLEVEL_HINTS:        targetClass = [CDLCTwoLevelHints class]; break;
74         case LC_PREBIND_CKSUM:         targetClass = [CDLCPrebindChecksum class]; break;
75         case LC_LOAD_WEAK_DYLIB:       targetClass = [CDLCDylib class]; break;
76         case LC_ROUTINES_64:           targetClass = [CDLCRoutines64 class]; break;
77         case LC_UUID:                  targetClass = [CDLCUUID class]; break;
78         case LC_RPATH:                 targetClass = [CDLCRunPath class]; break;
79         case LC_CODE_SIGNATURE:        targetClass = [CDLCLinkeditData class]; break;
80         case LC_SEGMENT_SPLIT_INFO:    targetClass = [CDLCLinkeditData class]; break;
81         case LC_REEXPORT_DYLIB:        targetClass = [CDLCDylib class]; break;
82         case LC_LAZY_LOAD_DYLIB:       targetClass = [CDLCDylib class]; break;
83         case LC_ENCRYPTION_INFO:
84         case LC_ENCRYPTION_INFO_64:    targetClass = [CDLCEncryptionInfo class]; break;
85         case LC_DYLD_INFO:             targetClass = [CDLCDyldInfo class]; break;
86         case LC_DYLD_INFO_ONLY:        targetClass = [CDLCDyldInfo class]; break;
88         case LC_LOAD_UPWARD_DYLIB:     targetClass = [CDLCDylib class]; break;
89         case LC_VERSION_MIN_MACOSX:    targetClass = [CDLCVersionMinimum class]; break;
90         case LC_VERSION_MIN_IPHONEOS:  targetClass = [CDLCVersionMinimum class]; break;
91         case LC_FUNCTION_STARTS:       targetClass = [CDLCFunctionStarts class]; break;
92         case LC_DYLD_ENVIRONMENT:      targetClass = [CDLCDylinker class]; break;
93         case LC_MAIN:                  targetClass = [CDLCMain class]; break;
94         case LC_DATA_IN_CODE:          targetClass = [CDLCDataInCode class]; break;
95         case LC_SOURCE_VERSION:        targetClass = [CDLCSourceVersion class]; break;
96         case LC_DYLIB_CODE_SIGN_DRS:   targetClass = [CDLCLinkeditData class]; break; // Designated Requirements
98         case LC_BUILD_VERSION:         targetClass = [CDLCBuildVersion class]; break;
100         case LC_LINKER_OPTION:
101         case LC_LINKER_OPTIMIZATION_HINT:
102         case LC_VERSION_MIN_TVOS:
103         case LC_VERSION_MIN_WATCHOS:
104         case LC_NOTE:
106         default:
107             NSLog(@"Unknown load command: 0x%08x", val);
108     };
110     //NSLog(@"targetClass: %@", NSStringFromClass(targetClass));
112     return [[targetClass alloc] initWithDataCursor:cursor];
115 - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
117     if ((self = [super init])) {
118         _machOFile = [cursor machOFile];
119         _commandOffset = [cursor offset];
120     }
122     return self;
125 #pragma mark - Debugging
127 - (NSString *)description;
129     return [NSString stringWithFormat:@"<%@:%p> cmd: 0x%08x (%@), cmdsize: %d // %@",
130             NSStringFromClass([self class]), self,
131             self.cmd, self.commandName, self.cmdsize, [self extraDescription]];
134 - (NSString *)extraDescription;
136     return @"";
139 #pragma mark -
141 - (uint32_t)cmd;
143     // Implement in subclasses
144     [NSException raise:NSGenericException format:@"Must implement method in subclasses."];
145     return 0;
148 - (uint32_t)cmdsize;
150     // Implement in subclasses
151     [NSException raise:NSGenericException format:@"Must implement method in subclasses."];
152     return 0;
155 - (BOOL)mustUnderstandToExecute;
157     return (self.cmd & LC_REQ_DYLD) != 0;
160 - (NSString *)commandName;
162     switch (self.cmd) {
163         case LC_SEGMENT:               return @"LC_SEGMENT";
164         case LC_SYMTAB:                return @"LC_SYMTAB";
165         case LC_SYMSEG:                return @"LC_SYMSEG";
166         case LC_THREAD:                return @"LC_THREAD";
167         case LC_UNIXTHREAD:            return @"LC_UNIXTHREAD";
168         case LC_LOADFVMLIB:            return @"LC_LOADFVMLIB";
169         case LC_IDFVMLIB:              return @"LC_IDFVMLIB";
170         case LC_IDENT:                 return @"LC_IDENT";
171         case LC_FVMFILE:               return @"LC_FVMFILE";
172         case LC_PREPAGE:               return @"LC_PREPAGE";
173         case LC_DYSYMTAB:              return @"LC_DYSYMTAB";
174         case LC_LOAD_DYLIB:            return @"LC_LOAD_DYLIB";
175         case LC_ID_DYLIB:              return @"LC_ID_DYLIB";
176         case LC_LOAD_DYLINKER:         return @"LC_LOAD_DYLINKER";
177         case LC_ID_DYLINKER:           return @"LC_ID_DYLINKER";
178         case LC_PREBOUND_DYLIB:        return @"LC_PREBOUND_DYLIB";
179         case LC_ROUTINES:              return @"LC_ROUTINES";
180         case LC_SUB_FRAMEWORK:         return @"LC_SUB_FRAMEWORK";
181         case LC_SUB_UMBRELLA:          return @"LC_SUB_UMBRELLA";
182         case LC_SUB_CLIENT:            return @"LC_SUB_CLIENT";
183         case LC_SUB_LIBRARY:           return @"LC_SUB_LIBRARY";
184         case LC_TWOLEVEL_HINTS:        return @"LC_TWOLEVEL_HINTS";
185         case LC_PREBIND_CKSUM:         return @"LC_PREBIND_CKSUM";
186             
187         case LC_LOAD_WEAK_DYLIB:       return @"LC_LOAD_WEAK_DYLIB";
188         case LC_SEGMENT_64:            return @"LC_SEGMENT_64";
189         case LC_ROUTINES_64:           return @"LC_ROUTINES_64";
190         case LC_UUID:                  return @"LC_UUID";
191         case LC_RPATH:                 return @"LC_RPATH";
192         case LC_CODE_SIGNATURE:        return @"LC_CODE_SIGNATURE";
193         case LC_SEGMENT_SPLIT_INFO:    return @"LC_SEGMENT_SPLIT_INFO";
194         case LC_REEXPORT_DYLIB:        return @"LC_REEXPORT_DYLIB";
195         case LC_LAZY_LOAD_DYLIB:       return @"LC_LAZY_LOAD_DYLIB";
196         case LC_ENCRYPTION_INFO:       return @"LC_ENCRYPTION_INFO";
197         case LC_DYLD_INFO:             return @"LC_DYLD_INFO";
198         case LC_DYLD_INFO_ONLY:        return @"LC_DYLD_INFO_ONLY";
199         case LC_LOAD_UPWARD_DYLIB:     return @"LC_LOAD_UPWARD_DYLIB";
200         case LC_VERSION_MIN_MACOSX:    return @"LC_VERSION_MIN_MACOSX";
201         case LC_VERSION_MIN_IPHONEOS:  return @"LC_VERSION_MIN_IPHONEOS";
202         case LC_FUNCTION_STARTS:       return @"LC_FUNCTION_STARTS";
203         case LC_DYLD_ENVIRONMENT:      return @"LC_DYLD_ENVIRONMENT";
205         case LC_LINKER_OPTION:            return @"LC_LINKER_OPTION";
206         case LC_LINKER_OPTIMIZATION_HINT: return @"LC_LINKER_OPTIMIZATION_HINT";
207         case LC_VERSION_MIN_TVOS:         return @"LC_VERSION_MIN_TVOS";
208         case LC_VERSION_MIN_WATCHOS:      return @"LC_VERSION_MIN_WATCHOS";
209         case LC_NOTE:                     return @"LC_NOTE";
210         case LC_BUILD_VERSION:            return @"LC_BUILD_VERSION";
212         default:
213             break;
214     }
216     return [NSString stringWithFormat:@"0x%08x", [self cmd]];
219 - (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose;
221     [resultString appendFormat:@"     cmd %@", [self commandName]];
222     if (self.mustUnderstandToExecute)
223         [resultString appendFormat:@" (must understand to execute)"];
224     [resultString appendFormat:@"\n"];
225     [resultString appendFormat:@" cmdsize %u\n", [self cmdsize]];
228 - (void)machOFileDidReadLoadCommands:(CDMachOFile *)machOFile;
232 @end