#include <dispatch/dispatch.h>
#include <uuid/uuid.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach-o/loader.h>
#include <sys/types.h>
#include <execinfo.h>
#include <stdio.h>
#include <dlfcn.h>
#include <asl.h>
#include <errno.h>
#include "assumes.h"
#if 0
static char __crashreporter_info_buff__[2048];
const char *__crashreporter_info__ = &__crashreporter_info_buff__[0];
asm (".desc __crashreporter_info__, 0x10");
#endif
#define osx_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
static const char *
_osx_basename(const char *p)
{
return ((strrchr(p, '/') ? : p - 1) + 1);
}
static char *
_osx_get_build(void)
{
static char s_build[16];
static long s_once = 0;
if (osx_atomic_cmpxchg(&s_once, 0, 1)) {
int mib[] = { CTL_KERN, KERN_OSVERSION };
size_t sz = sizeof(s_build);
(void)sysctl(mib, 2, s_build, &sz, NULL, 0);
}
return s_build;
}
static void
_osx_get_image_uuid(void *hdr, uuid_t uuid)
{
#if __LP64__
struct mach_header_64 *_hdr = (struct mach_header_64 *)hdr;
#else
struct mach_header *_hdr = (struct mach_header *)hdr;
#endif
size_t i = 0;
size_t next = sizeof(*_hdr);
struct load_command *cur = NULL;
for (i = 0; i < _hdr->ncmds; i++) {
cur = (struct load_command *)((uintptr_t)_hdr + next);
if (cur->cmd == LC_UUID) {
struct uuid_command *cmd = (struct uuid_command *)cur;
uuid_copy(uuid, cmd->uuid);
break;
}
next += cur->cmdsize;
}
if (i == _hdr->ncmds) {
uuid_clear(uuid);
}
}
void
_osx_assumes_log(uint64_t code)
{
Dl_info info;
const char *image_name = NULL;
uintptr_t offset = 0;
uuid_string_t uuid_str;
void *arr[2];
if (backtrace(arr, 2) == 2) {
if (dladdr(arr[1], &info)) {
uuid_t uuid;
_osx_get_image_uuid(info.dli_fbase, uuid);
uuid_unparse(uuid, uuid_str);
image_name = _osx_basename(info.dli_fname);
offset = arr[1] - info.dli_fbase;
}
} else {
uuid_t null_uuid;
uuid_string_t uuid_str;
uuid_clear(null_uuid);
uuid_unparse(null_uuid, uuid_str);
image_name = "unknown";
}
char name[256];
(void)snprintf(name, sizeof(name), "com.apple.assumes.%s", image_name);
char sig[64];
(void)snprintf(sig, sizeof(sig), "%s:%lu", uuid_str, offset);
char result[24];
(void)snprintf(result, sizeof(result), "0x%llx", code);
char *prefix = "Bug";
char message[1024];
(void)snprintf(message, sizeof(message), "%s: %s: %s + %lu [%s]: %s", prefix, _osx_get_build(), image_name, offset, uuid_str, result);
aslmsg msg = asl_new(ASL_TYPE_MSG);
if (msg != NULL) {
(void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
(void)asl_set(msg, "com.apple.message.domain", name);
(void)asl_set(msg, "com.apple.message.signature", sig);
(void)asl_set(msg, "com.apple.message.value", result);
(void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
asl_free(msg);
}
}
#if 0
void
osx_hardware_trap(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
osx_hardware_trapv(fmt, ap);
va_end(ap);
}
void
osx_hardware_trapv(const char *fmt, va_list ap)
{
(void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), fmt, ap);
fflush(NULL);
__builtin_trap();
}
#endif