FIRCLSMachOTests.m 12 KB

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