in Source/PLCrashLogWriter.m [300:478]
plcrash_error_t plcrash_log_writer_init (plcrash_log_writer_t *writer,
NSString *app_identifier,
NSString *app_version,
NSString *app_marketing_version,
plcrash_async_symbol_strategy_t symbol_strategy,
BOOL user_requested)
{
/* Default to 0 */
memset(writer, 0, sizeof(*writer));
/* Initialize configuration */
writer->symbol_strategy = symbol_strategy;
/* Default to false */
writer->report_info.user_requested = user_requested;
/* Generate a UUID for this incident; CFUUID is used in favor of NSUUID as to maintain compatibility
* with (Mac OS X 10.7|iOS 5) and earlier. */
{
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
PLCF_ASSERT(sizeof(bytes) == sizeof(writer->report_info.uuid_bytes));
memcpy(writer->report_info.uuid_bytes, &bytes, sizeof(writer->report_info.uuid_bytes));
CFRelease(uuid);
}
/* Fetch the application information */
{
plprotobuf_cbinary_data_nsstring_init(&writer->application_info.app_identifier, app_identifier);
plprotobuf_cbinary_data_nsstring_init(&writer->application_info.app_version, app_version);
if (app_marketing_version != nil) {
plprotobuf_cbinary_data_nsstring_init(&writer->application_info.app_marketing_version, app_marketing_version);
}
}
/* Fetch the process information */
{
/* Current process */
PLCrashProcessInfo *pinfo = [PLCrashProcessInfo currentProcessInfo];
if (pinfo == nil) {
/* Should only occur if the process is no longer valid */
PLCF_DEBUG("Could not retreive process info for target");
return PLCRASH_EINVAL;
}
{
/* Retrieve PID */
writer->process_info.process_id = pinfo.processID;
/* Retrieve name and start time. */
if (pinfo.processName != nil) {
plprotobuf_cbinary_data_nsstring_init(&writer->process_info.process_name, pinfo.processName);
}
writer->process_info.start_time = pinfo.startTime.tv_sec;
/* Retrieve path */
uint32_t process_path_len = 0;
_NSGetExecutablePath(NULL, &process_path_len);
if (process_path_len > 0) {
char *process_path = malloc(process_path_len);
_NSGetExecutablePath(process_path, &process_path_len);
writer->process_info.process_path.data = process_path;
writer->process_info.process_path.len = process_path_len;
}
}
/* Parent process */
{
/* Retrieve PID */
writer->process_info.parent_process_id = pinfo.parentProcessID;
/* Retrieve name. This will fail on iOS 9+, where EPERM is returned due to new sandbox constraints. */
PLCrashProcessInfo *parentInfo = [[PLCrashProcessInfo alloc] initWithProcessID: pinfo.parentProcessID];
if (parentInfo != nil) {
if (parentInfo.processName != nil) {
plprotobuf_cbinary_data_nsstring_init(&writer->process_info.parent_process_name, parentInfo.processName);
}
} else {
PLCF_DEBUG("Could not retreive parent process name: %s", strerror(errno));
}
}
}
/* Fetch the machine information */
{
/* Model */
#if TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST
/* On iOS, we want hw.machine (e.g. hw.machine = iPad2,1; hw.model = K93AP) */
char *model = plcrash_sysctl_string("hw.machine");
#else
/* On Mac OS X, we want hw.model (e.g. hw.machine = x86_64; hw.model = Macmini5,3) */
char *model = plcrash_sysctl_string("hw.model");
#endif
if (model == NULL) {
PLCF_DEBUG("Could not retrive hw.model: %s", strerror(errno));
}
plprotobuf_cbinary_data_string_init(&writer->machine_info.model, model);
/* CPU */
{
int retval;
/* Fetch the CPU types */
if (plcrash_sysctl_int("hw.cputype", &retval)) {
writer->machine_info.cpu_type = retval;
} else {
PLCF_DEBUG("Could not retrive hw.cputype: %s", strerror(errno));
}
if (plcrash_sysctl_int("hw.cpusubtype", &retval)) {
writer->machine_info.cpu_subtype = retval;
} else {
PLCF_DEBUG("Could not retrive hw.cpusubtype: %s", strerror(errno));
}
/* Processor count */
if (plcrash_sysctl_int("hw.physicalcpu_max", &retval)) {
writer->machine_info.processor_count = retval;
} else {
PLCF_DEBUG("Could not retrive hw.physicalcpu_max: %s", strerror(errno));
}
if (plcrash_sysctl_int("hw.logicalcpu_max", &retval)) {
writer->machine_info.logical_processor_count = retval;
} else {
PLCF_DEBUG("Could not retrive hw.logicalcpu_max: %s", strerror(errno));
}
}
/*
* Check if the process is emulated. This sysctl is defined in the Universal Binary Programming Guidelines,
* Second Edition:
*
* http://developer.apple.com/legacy/mac/library/documentation/MacOSX/Conceptual/universal_binary/universal_binary.pdf
*/
{
int retval;
if (plcrash_sysctl_int("sysctl.proc_native", &retval)) {
if (retval == 0) {
writer->process_info.native = false;
} else {
writer->process_info.native = true;
}
} else {
/* If the sysctl is not available, the process can be assumed to be native. */
writer->process_info.native = true;
}
}
}
/* Fetch the OS information */
char *build = plcrash_sysctl_string("kern.osversion");
if (build == NULL) {
PLCF_DEBUG("Could not retrive kern.osversion: %s", strerror(errno));
}
plprotobuf_cbinary_data_string_init(&writer->system_info.build, build);
#if TARGET_OS_IPHONE || TARGET_OS_MAC
/* iOS, tvOS, macOS and Mac Catalyst */
{
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
NSOperatingSystemVersion systemVersion = processInfo.operatingSystemVersion;
NSString *systemVersionString = [NSString stringWithFormat:@"%ld.%ld", (long)systemVersion.majorVersion, (long)systemVersion.minorVersion];
if (systemVersion.patchVersion > 0) {
systemVersionString = [systemVersionString stringByAppendingFormat:@".%ld", (long)systemVersion.patchVersion];
}
plprotobuf_cbinary_data_nsstring_init(&writer->system_info.version, systemVersionString);
}
#else
#error Unsupported Platform
#endif
/* Ensure that any signal handler has a consistent view of the above initialization. */
atomic_thread_fence(memory_order_seq_cst);
return PLCRASH_ESUCCESS;
}