FIRCLSMachOTests.m 11 KB

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