Skip to content

Instantly share code, notes, and snippets.

@annidy
Forked from michaeleisel/a.m
Last active September 27, 2024 13:19
Show Gist options
  • Save annidy/bad51b21184767a64bce1693349aad64 to your computer and use it in GitHub Desktop.
Save annidy/bad51b21184767a64bce1693349aad64 to your computer and use it in GitHub Desktop.
//Copyright (c) 2018 Michael Eisel. All rights reserved.
#import "CLRCallRecorder.h"
#import <dlfcn.h>
#import <libkern/OSAtomicQueue.h>
#import <pthread.h>
typedef struct {
void *ptr;
NSInteger number;
} CLRCall;
static OSQueueHead sQueueData = OS_ATOMIC_QUEUE_INIT;
static OSQueueHead *sQueue = &sQueueData;
static BOOL sStopCollecting = NO;
static BOOL sInitDidOccur = NO;
typedef struct {
void *pointer;
void *next;
} PointerNode;
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
sInitDidOccur = YES;
for (uint32_t *x = start; x < stop; x++) {
*x = 1;
}
}
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// If initialization has not occurred yet (meaning that guard is uninitialized), that means that initial functions like +load are being run. These functions will only be run once anyways, so we should always allow them to be recorded and ignore guard
if (sStopCollecting || (!(*guard) && sInitDidOccur)) {
return;
}
*guard = 0;
void *pointer = __builtin_return_address(0);
PointerNode *node = malloc(sizeof(PointerNode));
*node = (PointerNode){pointer, NULL};
OSAtomicEnqueue(sQueue, node, offsetof(PointerNode, next));
}
extern NSArray <NSString *> *CLRCollectCalls(void) {
sStopCollecting = YES;
__sync_synchronize();
// Hopefully, any other threads for which sStopCollecting was NO when they entered and are still preempted will get to preempt
// during this sleep and finish up
sleep(1);
NSMutableArray <NSString *> *functions = [NSMutableArray array];
while (YES) {
PointerNode *node = OSAtomicDequeue(sQueue, offsetof(PointerNode, next));
if (node == NULL) {
break;
}
Dl_info info = {0};
dladdr(node->pointer, &info);
NSString *name = @(info.dli_sname);
BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString *symbolName = isObjc ? name : [@"_" stringByAppendingString:name];
[functions addObject:symbolName];
}
NSOrderedSet *set = [NSOrderedSet orderedSetWithArray:functions];
return [[set reverseObjectEnumerator] allObjects];}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment