一、xctest
1.xctest 的作用
XCTest是Xcode自带的单元测验框架,咱们可以运用该框架做功能性代码的白盒单元测验,以自测并增强代码健壮性。
创立时勾选:
咱们经过一个工程来了解xctest:
编译运行,检查生成目录:
检查符号(指令):
objdump --macho --private-headers path/path
现在咱们来找到xctest.framwork
在什么位置
经过创立LGXCTestCenter 来进行单元测验:
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
NS_ASSUME_NONNULL_BEGIN
@interface LGXCTestCenter : XCTestSuite
+ (instancetype)testSuiteForTestCaseClassString:(NSString *)cls;
@end
NS_ASSUME_NONNULL_END
#import "LGXCTestCenter.h"
@implementation LGXCTestCenter
+ (instancetype)testSuiteForTestCaseClassString:(NSString *)cls {
Class cl = NSClassFromString(cls);
if (cl) {
return [self testSuiteForTestCaseClass:cl];
}
return nil;
}
@end
需要装备xcconfig:
确保可以加载到xctest.framework :
#include "Pods/Target Support Files/Pods-LoginApp/Pods-LoginApp.debug.xcconfig"
// framework
XCODE_XCTEST_PATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks
FRAMEWORK_SEARCH_PATHS = ${XCODE_XCTEST_PATH}
// ld framework
//OTHER_LDFLAGS = -framework XCTest
二、dSYM
dSYM
文件就是保存按DWARF
格式保存调试信息的文件;
DWARF
是一种被众多编译器和调试器运用的用于支撑源代码等级调试的调试文件格式。
运用指令检查.o的__DWARF
objdump --macho --private-headers test.o
咱们在运行时调试到的地址实际上是 调试地址 = 虚拟地址 + ASLR
dSYM
文件内保存的是没有偏移的虚拟地址还是偏移后的地址?
经过指令检查:
经过研究 LLVM源码来探索。
三、溃散日志
经过指令检查地址在 .dSYM
内的DWARF
信息:
dwarfdump --lookup 0x100000f20 --arch=x86_64 test.dSYM
如何导出 .dSYM:
在设置 shell 脚本 编译生成项目导出 dSYM:
运行项目 溃散的日志信息: 经过指令检查 macho 汇编代码:
objdump --macho -d /path
四、二进制
ASLR 内存偏移算法:
@implementation ViewController
// 偏移
// dsym --> 没
uintptr_t get_slide_address(void) {
uintptr_t vmaddr_slide = 0;
// dyld 加载了多少image
for (uint32_t i = 0; i < _dyld_image_count(); i++) {
// index dyld加载的imgae name
const char *image_name = (char *)_dyld_get_image_name(i);
const struct mach_header *header = _dyld_get_image_header(i);
// macho EXEC MH_EXECUTE
if (header->filetype == MH_EXECUTE) {
// ASLR
vmaddr_slide = _dyld_get_image_vmaddr_slide(i);
}
NSString *str = [NSString stringWithUTF8String:image_name];
if ([str containsString:@"TestInject"]) {
NSLog(@"Image name %s at address 0x%llx and ASLR slide 0x%lx.n", image_name, (mach_vm_address_t)header, vmaddr_slide);
break;
}
}
return (uintptr_t)vmaddr_slide;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self getMethodVMA];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self test_dwarf];
});
NSLog(@"123");
}
- (void)test_dwarf {
NSArray *array = @[];
array[1];
}
- (void)getMethodVMA {
// imp 调用
IMP imp = (IMP)class_getMethodImplementation(self.class, @selector(test_dwarf));
unsigned long imppos = (unsigned long)imp;
// 偏移量
unsigned long slide = get_slide_address();
// imp - 偏移量
unsigned long addr = imppos - slide;
NSLog(@"%lx-- %lx", addr, imp);
}
/**
ASLR 0x8c03000
没: 100001d00
偏移:108c04d00
*/
@end
/**
0x000000000f0aa000
0x0000000100001d20
*/
拿到没有偏移的地址,进行读取dSYM检查测验单元信息。
dwarfdump --lookup 0x100001d00 test.dSYM
如果是.a 库,是.dylib库 出错了,怎样检查dSYM文件的错误信息。
在lldb 中设置断点。
只需要在dSYM信息中的地址中,添加对应的源码文件。就能app工程中止点到framework库中的代码。
经过指令生成 SDWebImage.a库
xcframework gen --use-libraries --configuration=Debug --output-dir="../App"
产物目录/include –>xcode 会copy一份你运用的框架到 产物目录/同时copy