FIRCLSMachOTests.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Copyright 2019 Google
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "Crashlytics/UnitTests/FIRCLSMachO/FIRCLSMachOTests.h"
  15. #include <mach-o/dyld.h>
  16. #include <mach-o/getsect.h>
  17. #include <mach-o/utils.h>
  18. #include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"
  19. #import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h"
  20. #import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h"
  21. #import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h"
  22. #import "Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h"
  23. @implementation FIRCLSMachOTests
  24. - (NSString*)resourcePath {
  25. #if SWIFT_PACKAGE
  26. NSBundle* bundle = SWIFTPM_MODULE_BUNDLE;
  27. return [bundle.resourcePath stringByAppendingPathComponent:@"machO_data"];
  28. #else
  29. NSBundle* bundle = [NSBundle bundleForClass:[self class]];
  30. return bundle.resourcePath;
  31. #endif
  32. }
  33. - (NSArray*)sortedArchitectures:(id)obj {
  34. NSMutableArray* archs;
  35. archs = [NSMutableArray array];
  36. [obj enumerateUUIDs:^(NSString* uuid, NSString* architecture) {
  37. [archs addObject:architecture];
  38. }];
  39. // sort the array, so we always get back the results in the same order
  40. [archs sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  41. return [obj1 caseInsensitiveCompare:obj2];
  42. }];
  43. return archs;
  44. }
  45. - (void)testThinDSYM {
  46. FIRCLSdSYM* dSYM;
  47. NSString* path;
  48. NSArray* archs;
  49. path = [[self resourcePath] stringByAppendingPathComponent:@"i386-simulator.dSYM"];
  50. dSYM = [FIRCLSdSYM dSYMWithURL:[NSURL fileURLWithPath:path]];
  51. archs = [self sortedArchitectures:dSYM];
  52. XCTAssertEqual((NSUInteger)1, [archs count], @"");
  53. XCTAssertEqualObjects(@"i386", [archs objectAtIndex:0], @"");
  54. }
  55. - (void)testFatDSYM {
  56. FIRCLSdSYM* dSYM;
  57. NSString* path;
  58. NSArray* archs;
  59. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s.dSYM"];
  60. dSYM = [FIRCLSdSYM dSYMWithURL:[NSURL fileURLWithPath:path]];
  61. archs = [self sortedArchitectures:dSYM];
  62. XCTAssertEqual((NSUInteger)2, [archs count], @"");
  63. XCTAssertEqualObjects(@"armv7", [archs objectAtIndex:0], @"");
  64. XCTAssertEqualObjects(@"armv7s", [archs objectAtIndex:1], @"");
  65. }
  66. - (void)testFatExecutable {
  67. FIRCLSMachOBinary* binary;
  68. NSString* path;
  69. NSArray* archs;
  70. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s-executable"];
  71. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  72. archs = [self sortedArchitectures:binary];
  73. XCTAssertEqual((NSUInteger)2, [archs count], @"");
  74. XCTAssertEqualObjects(@"armv7", [archs objectAtIndex:0], @"");
  75. XCTAssertEqualObjects(@"armv7s", [archs objectAtIndex:1], @"");
  76. }
  77. - (void)testArm64 {
  78. FIRCLSMachOBinary* binary;
  79. NSString* path;
  80. NSArray* archs;
  81. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s-arm64.dylib"];
  82. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  83. archs = [self sortedArchitectures:binary];
  84. XCTAssertEqual((NSUInteger)3, [archs count], @"");
  85. XCTAssertEqualObjects(@"arm64", [archs objectAtIndex:0], @"");
  86. XCTAssertEqualObjects(@"armv7", [archs objectAtIndex:1], @"");
  87. XCTAssertEqualObjects(@"armv7s", [archs objectAtIndex:2], @"");
  88. }
  89. - (void)testArmv7k {
  90. FIRCLSMachOBinary* binary;
  91. NSString* path;
  92. NSArray* archs;
  93. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7k"];
  94. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  95. archs = [self sortedArchitectures:binary];
  96. XCTAssertEqual((NSUInteger)1, [archs count], @"");
  97. XCTAssertEqualObjects(@"armv7k", [archs objectAtIndex:0], @"");
  98. }
  99. - (void)testReadMinimumWatchOSSDKRequirements {
  100. FIRCLSMachOBinary* binary;
  101. FIRCLSMachOSlice* slice;
  102. NSString* path;
  103. FIRCLSMachOVersion version;
  104. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7k"];
  105. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  106. slice = [binary sliceForArchitecture:@"armv7k"];
  107. version = [slice minimumOSVersion];
  108. XCTAssertEqual((uint32_t)2, version.major, @"");
  109. XCTAssertEqual((uint32_t)0, version.minor, @"");
  110. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  111. version = [slice linkedSDKVersion];
  112. XCTAssertEqual((uint32_t)2, version.major, @"");
  113. XCTAssertEqual((uint32_t)0, version.minor, @"");
  114. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  115. }
  116. - (void)testReadMinimumWatchOSSimulatorSDKRequirements {
  117. FIRCLSMachOBinary* binary;
  118. FIRCLSMachOSlice* slice;
  119. NSString* path;
  120. FIRCLSMachOVersion version;
  121. path = [[self resourcePath] stringByAppendingPathComponent:@"watchOS-simulator"];
  122. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  123. slice = [binary sliceForArchitecture:@"i386"];
  124. version = [slice minimumOSVersion];
  125. XCTAssertEqual((uint32_t)2, version.major, @"");
  126. XCTAssertEqual((uint32_t)0, version.minor, @"");
  127. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  128. version = [slice linkedSDKVersion];
  129. XCTAssertEqual((uint32_t)2, version.major, @"");
  130. XCTAssertEqual((uint32_t)0, version.minor, @"");
  131. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  132. }
  133. - (void)testReadMinimumTVOSSDKRequirements {
  134. FIRCLSMachOBinary* binary;
  135. FIRCLSMachOSlice* slice;
  136. NSString* path;
  137. FIRCLSMachOVersion version;
  138. path = [[self resourcePath] stringByAppendingPathComponent:@"tvos-binary"];
  139. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  140. slice = [binary sliceForArchitecture:@"arm64"];
  141. version = [slice minimumOSVersion];
  142. XCTAssertEqual((uint32_t)8, version.major, @"");
  143. XCTAssertEqual((uint32_t)0, version.minor, @"");
  144. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  145. version = [slice linkedSDKVersion];
  146. XCTAssertEqual((uint32_t)9, version.major, @"");
  147. XCTAssertEqual((uint32_t)0, version.minor, @"");
  148. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  149. }
  150. - (void)testReadMinimumTVOSSimulatorSDKRequirements {
  151. FIRCLSMachOBinary* binary;
  152. FIRCLSMachOSlice* slice;
  153. NSString* path;
  154. FIRCLSMachOVersion version;
  155. path = [[self resourcePath] stringByAppendingPathComponent:@"tvsimulator-binary"];
  156. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  157. slice = [binary sliceForArchitecture:@"x86_64"];
  158. version = [slice minimumOSVersion];
  159. XCTAssertEqual((uint32_t)8, version.major, @"");
  160. XCTAssertEqual((uint32_t)0, version.minor, @"");
  161. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  162. version = [slice linkedSDKVersion];
  163. XCTAssertEqual((uint32_t)9, version.major, @"");
  164. XCTAssertEqual((uint32_t)0, version.minor, @"");
  165. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  166. }
  167. - (void)testLinkedDylibs {
  168. FIRCLSMachOBinary* binary;
  169. FIRCLSMachOSlice* slice;
  170. NSString* path;
  171. NSArray* dylibs;
  172. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s-executable"];
  173. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  174. slice = [binary sliceForArchitecture:@"armv7"];
  175. XCTAssertNotNil(slice, @"");
  176. dylibs = [[slice linkedDylibs] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  177. return [obj1 compare:obj2 options:NSCaseInsensitiveSearch];
  178. }];
  179. XCTAssertEqual([dylibs count], (NSUInteger)7, @"");
  180. XCTAssertEqualObjects([dylibs objectAtIndex:0],
  181. @"/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", @"");
  182. XCTAssertEqualObjects([dylibs objectAtIndex:1],
  183. @"/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics", @"");
  184. XCTAssertEqualObjects([dylibs objectAtIndex:2],
  185. @"/System/Library/Frameworks/Foundation.framework/Foundation", @"");
  186. XCTAssertEqualObjects([dylibs objectAtIndex:3],
  187. @"/System/Library/Frameworks/UIKit.framework/UIKit", @"");
  188. XCTAssertEqualObjects([dylibs objectAtIndex:4], @"/usr/lib/libobjc.A.dylib", @"");
  189. XCTAssertEqualObjects([dylibs objectAtIndex:5], @"/usr/lib/libstdc++.6.dylib", @"");
  190. XCTAssertEqualObjects([dylibs objectAtIndex:6], @"/usr/lib/libSystem.B.dylib", @"");
  191. }
  192. - (void)testReadMinimumiOSSDKRequirements {
  193. FIRCLSMachOBinary* binary;
  194. FIRCLSMachOSlice* slice;
  195. NSString* path;
  196. FIRCLSMachOVersion version;
  197. path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s-executable"];
  198. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  199. slice = [binary sliceForArchitecture:@"armv7"];
  200. version = [slice minimumOSVersion];
  201. XCTAssertEqual((uint32_t)5, version.major, @"");
  202. XCTAssertEqual((uint32_t)1, version.minor, @"");
  203. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  204. version = [slice linkedSDKVersion];
  205. XCTAssertEqual((uint32_t)6, version.major, @"");
  206. XCTAssertEqual((uint32_t)0, version.minor, @"");
  207. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  208. }
  209. - (void)testReadMinimumOSXSDKRequirements {
  210. FIRCLSMachOBinary* binary;
  211. FIRCLSMachOSlice* slice;
  212. NSString* path;
  213. FIRCLSMachOVersion version;
  214. path = [[self resourcePath] stringByAppendingPathComponent:@"x86_64-executable"];
  215. binary = [FIRCLSMachOBinary MachOBinaryWithPath:path];
  216. slice = [binary sliceForArchitecture:@"x86_64"];
  217. version = [slice minimumOSVersion];
  218. XCTAssertEqual((uint32_t)10, version.major, @"");
  219. XCTAssertEqual((uint32_t)7, version.minor, @"");
  220. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  221. version = [slice linkedSDKVersion];
  222. XCTAssertEqual((uint32_t)10, version.major, @"");
  223. XCTAssertEqual((uint32_t)8, version.minor, @"");
  224. XCTAssertEqual((uint32_t)0, version.bugfix, @"");
  225. }
  226. - (void)testReadx86_64Section {
  227. NSString* path = [[self resourcePath] stringByAppendingPathComponent:@"x86_64-executable"];
  228. struct FIRCLSMachOFile file;
  229. XCTAssert(FIRCLSMachOFileInitWithPath(&file, [path fileSystemRepresentation]));
  230. struct FIRCLSMachOSlice slice = FIRCLSMachOFileSliceWithArchitectureName(&file, "x86_64");
  231. XCTAssert(FIRCLSMachOSliceIs64Bit(&slice));
  232. FIRCLSMachOSection section;
  233. XCTAssert(FIRCLSMachOSliceInitSectionByName(&slice, SEG_TEXT, "__eh_frame", &section));
  234. XCTAssertEqual(section.addr, 0x10001c9e0);
  235. XCTAssertEqual(section.offset, 117216);
  236. XCTAssertEqual(section.size, 0x2618);
  237. const void* ptr = NULL;
  238. XCTAssert(FIRCLSMachOSliceGetSectionByName(&slice, SEG_TEXT, "__eh_frame", &ptr));
  239. XCTAssert(ptr != NULL);
  240. }
  241. - (void)testReadArmv7kSection {
  242. NSString* path = [[self resourcePath] stringByAppendingPathComponent:@"armv7k"];
  243. struct FIRCLSMachOFile file;
  244. XCTAssert(FIRCLSMachOFileInitWithPath(&file, [path fileSystemRepresentation]));
  245. struct FIRCLSMachOSlice slice = FIRCLSMachOFileSliceWithArchitectureName(&file, "armv7k");
  246. FIRCLSMachOSection section;
  247. XCTAssert(FIRCLSMachOSliceInitSectionByName(&slice, SEG_TEXT, "__unwind_info", &section));
  248. XCTAssertEqual(section.addr, 0x23c4c);
  249. XCTAssertEqual(section.offset, 130124);
  250. XCTAssertEqual(section.size, 0x000002d8);
  251. const void* ptr = NULL;
  252. XCTAssert(FIRCLSMachOSliceGetSectionByName(&slice, SEG_TEXT, "__unwind_info", &ptr));
  253. XCTAssert(ptr != NULL);
  254. }
  255. #if !CLS_TARGET_OS_VISION
  256. - (void)testReadArm64Section {
  257. NSString* path = [[self resourcePath] stringByAppendingPathComponent:@"armv7-armv7s-arm64.dylib"];
  258. struct FIRCLSMachOFile file;
  259. XCTAssert(FIRCLSMachOFileInitWithPath(&file, [path fileSystemRepresentation]));
  260. struct FIRCLSMachOSlice slice = FIRCLSMachOFileSliceWithArchitectureName(&file, "arm64");
  261. XCTAssert(FIRCLSMachOSliceIs64Bit(&slice));
  262. FIRCLSMachOSection section;
  263. XCTAssert(FIRCLSMachOSliceInitSectionByName(&slice, SEG_TEXT, "__unwind_info", &section));
  264. XCTAssertEqual(section.addr, 0x1ffa9);
  265. XCTAssertEqual(section.offset, 130985);
  266. XCTAssertEqual(section.size, 0x48);
  267. const void* ptr = NULL;
  268. XCTAssert(FIRCLSMachOSliceGetSectionByName(&slice, SEG_TEXT, "__unwind_info", &ptr));
  269. XCTAssert(ptr != NULL);
  270. }
  271. #endif
  272. #if CLS_TARGET_OS_VISION
  273. - (void)testVisionProGetSlice {
  274. struct FIRCLSMachOSlice slice = FIRCLSMachOSliceGetCurrent();
  275. XCTAssertEqual(slice.cputype, CPU_TYPE_ARM64);
  276. const char* archname = macho_arch_name_for_mach_header(NULL);
  277. XCTAssertEqualObjects(@(archname), @"arm64");
  278. }
  279. #endif
  280. @end