Clang principle

Clang document clang.llvm.org/docs/Saniti…

A code Tracing feature provided by Apple, Tracing PCs

Add -fsanitize-coverage=func,trace-pc-guard to xcode

Note the func here, which stands for intercepting methods only.

2. An error is reported at runtime because two methods are undefined

__sanitizer_cov_trace_pc_guard_init
__sanitizer_cov_trace_pc_guard
Copy the code

This is a callback that needs to be defined in the project as required by the documentation.

Command to view memory: x 0x100000

Methods, blocks, functions, and so on are collectively referred to as methods.

__sanitizer_cov_trace_pc_guard_init

You can get the number of all methods.

__sanitizer_cov_trace_pc_guard

Hook all methods and get the order in which they are called.

You add a line of code to the implementation of each method, and by calling the method, you modify the binary.

This method is also the principle of Clang piling.

Gets the symbol and stores it

Print all symbols as follows:

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    void *PC = __builtin_return_address(0);
    Dl_info info;
    dladdr(PC,&info);
    printf(@"%s\n",info.dli_sname);
}
Copy the code

The above callback method is multithreaded, that is, the function in the child thread is executed in the child thread.

So you need to store symbols in a thread-safe way, in a thread-safe atomic queue.

#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
#import <dlfcn.h>
#import <libkern/OSAtomic.h>


void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    void *PC = __builtin_return_address(0);
    Dl_info info;
    dladdr(PC,&info);
    printf(@"%s\n",info.dli_sname);
    // Create a structure
    SYNode * node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,NULL};
    // The structure is pushed
    OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
    
}


// Generate order file!!- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // Define an array
    NSMutableArray<NSString *> * symbleNames = [NSMutableArray array];
    
    while (YES) {// Circulating body! Intercept!!
        SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode,next));
        
        if (node == NULL) {
            break;
        }
        
        Dl_info info;
        dladdr(node->pc, &info);
        NSString * name = @(info.dli_sname);// Turn to string
        // Add _ to the function name
        BOOL isObjc = [name hasPrefix:@ "+ ["] || [name hasPrefix:@"-["];
        NSString * symbolName = isObjc ? name : [@ "_" stringByAppendingString:name];
        [symbleNames addObject:symbolName];
    }
    
    // Reverse traverse the number group
// symbleNames = (NSMutableArray
      
        *)[[symbleNames reverseObjectEnumerator] allObjects];
      
// NSLog(@"%@",symbleNames);
    NSEnumerator * em = [symbleNames reverseObjectEnumerator];
    NSMutableArray * funcs = [NSMutableArray arrayWithCapacity:symbleNames.count];
    NSString * name;
    / / to heavy
    while (name = [em nextObject]) {
        if (![funcs containsObject:name]) {
            [funcs addObject:name];
        }
    }
    // Remove yourself! touchesBegan
    [funcs removeObject:[NSString stringWithFormat:@"%s",__func__]];
    
    // Write to the file
    //1. Programming string
    NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"dd.order"];
    NSData * file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
    
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:nil];
    
    NSLog(@ "% @",funcStr);
}

Copy the code

Swift symbol coverage

1. Create a swift file

2. Add Other Swift Flags

And so the Swift method is added.