#ifdef _WIN32
#include <direct.h>
#include <process.h>
#include <windows.h>
#include "WindowsMMap.h"
#else
#include <errno.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#ifdef COMPILER_RT_HAS_UNAME
#include <sys/utsname.h>
#endif
#include <stdlib.h>
#include <string.h>
#if defined(__linux__)
#include <signal.h>
#include <sys/prctl.h>
#endif
#if defined(__Fuchsia__)
#include <zircon/process.h>
#include <zircon/syscalls.h>
#endif
#if defined(__FreeBSD__)
#include <signal.h>
#include <sys/procctl.h>
#endif
#include "InstrProfiling.h"
#include "InstrProfilingUtil.h"
COMPILER_RT_VISIBILITY unsigned lprofDirMode = …;
COMPILER_RT_VISIBILITY
void __llvm_profile_recursive_mkdir(char *path) { … }
COMPILER_RT_VISIBILITY
void __llvm_profile_set_dir_mode(unsigned Mode) { … }
COMPILER_RT_VISIBILITY
unsigned __llvm_profile_get_dir_mode(void) { … }
#if COMPILER_RT_HAS_ATOMICS != 1
COMPILER_RT_VISIBILITY
uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
void *R = *Ptr;
if (R == OldV) {
*Ptr = NewV;
return 1;
}
return 0;
}
COMPILER_RT_VISIBILITY
void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
void *Old = *Mem;
*((char **)Mem) += ByteIncr;
return Old;
}
#endif
#ifdef _WIN32
COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
WCHAR Buffer[COMPILER_RT_MAX_HOSTLEN];
DWORD BufferSize = sizeof(Buffer);
BOOL Result =
GetComputerNameExW(ComputerNameDnsFullyQualified, Buffer, &BufferSize);
if (!Result)
return -1;
if (WideCharToMultiByte(CP_UTF8, 0, Buffer, -1, Name, Len, NULL, NULL) == 0)
return -1;
return 0;
}
#elif defined(COMPILER_RT_HAS_UNAME)
COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) { … }
#endif
COMPILER_RT_VISIBILITY int lprofLockFd(int fd) { … }
COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) { … }
COMPILER_RT_VISIBILITY int lprofLockFileHandle(FILE *F) { … }
COMPILER_RT_VISIBILITY int lprofUnlockFileHandle(FILE *F) { … }
COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) { … }
COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip,
size_t *PrefixLen) { … }
COMPILER_RT_VISIBILITY void
lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
size_t PrefixLen, int PrefixStrip) { … }
COMPILER_RT_VISIBILITY const char *
lprofFindFirstDirSeparator(const char *Path) { … }
COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) { … }
COMPILER_RT_VISIBILITY int lprofSuspendSigKill(void) { … }
COMPILER_RT_VISIBILITY void lprofRestoreSigKill(void) { … }
COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
uintptr_t End) { … }
#ifdef _AIX
typedef struct fn_node {
AtExit_Fn_ptr func;
struct fn_node *next;
} fn_node;
typedef struct {
fn_node *top;
} fn_stack;
static void fn_stack_push(fn_stack *, AtExit_Fn_ptr);
static AtExit_Fn_ptr fn_stack_pop(fn_stack *);
static int fn_stack_is_empty(fn_stack *);
static fn_stack AtExit_stack = {0};
#define ATEXIT_STACK …
__attribute__((__destructor__)) static void cleanup() {
while (!fn_stack_is_empty(ATEXIT_STACK)) {
AtExit_Fn_ptr func = fn_stack_pop(ATEXIT_STACK);
if (func && unatexit(func) == 0)
func();
}
}
static void fn_stack_push(fn_stack *st, AtExit_Fn_ptr func) {
fn_node *old_top, *n = (fn_node *)malloc(sizeof(fn_node));
n->func = func;
while (1) {
old_top = st->top;
n->next = old_top;
if (COMPILER_RT_BOOL_CMPXCHG(&st->top, old_top, n))
return;
}
}
static AtExit_Fn_ptr fn_stack_pop(fn_stack *st) {
fn_node *old_top, *new_top;
while (1) {
old_top = st->top;
if (old_top == 0)
return 0;
new_top = old_top->next;
if (COMPILER_RT_BOOL_CMPXCHG(&st->top, old_top, new_top)) {
AtExit_Fn_ptr func = old_top->func;
free(old_top);
return func;
}
}
}
static int fn_stack_is_empty(fn_stack *st) { return st->top == 0; }
#endif
COMPILER_RT_VISIBILITY int lprofAtExit(AtExit_Fn_ptr func) { … }