Loading...
--- /dev/null
+++ dyld/dyld-421.1/interlinked-dylibs/Logging.cpp
@@ -0,0 +1,257 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <dispatch/dispatch.h>
+#include <string.h>
+#include <stdlib.h>
+#include <set>
+
+#include <assert.h>
+#include "mega-dylib-utils.h"
+
+#include "Logging.h"
+
+#define MAX_LOG_STR_LEN (512)
+//const char* kDispatchQueueLogNameKey = "kDispatchQueueLogNameKey";
+const char* kDispatchWarningArrayKey = "kDispatchWarningArrayKey";
+
+static dispatch_queue_t log_queue;
+static dispatch_once_t logQueueInit = 0;
+static dispatch_queue_t unique_queue;
+static dispatch_once_t uniqueQueueInit = 0;
+
+static uint32_t verbose = 0;
+static bool returnNonZeroIfTerminateCalled = false;
+static bool terminateCalled = false;
+
+static const char* warningPrefix = "WARNING: ";
+static const char* errorPrefix = "ERROR: ";
+
+LoggingContext::LoggingContext(const std::string& N)
+ : _name(N)
+ , _tainted(false)
+{
+}
+
+LoggingContext::LoggingContext(const std::string& N, WarningTargets T)
+ : _name(N)
+ , _warnings(T)
+ , _tainted(false)
+{
+}
+
+void LoggingContext::taint()
+{
+ _tainted = true;
+}
+
+bool LoggingContext::isTainted()
+{
+ return _tainted;
+}
+
+const std::string& LoggingContext::name()
+{
+ return _name;
+}
+
+const WarningTargets& LoggingContext::targets()
+{
+ return _warnings;
+}
+
+
+
+pthread_key_t getLoggingContextKey(void) {
+ static pthread_key_t logContextKey;
+ static dispatch_once_t logContextToken;
+ dispatch_once(&logContextToken, ^{
+ pthread_key_create(&logContextKey, nullptr);
+ });
+ return logContextKey;
+}
+
+
+void setLoggingContext(std::shared_ptr<LoggingContext>& context)
+{
+ pthread_setspecific(getLoggingContextKey(), (void*)&context);
+
+ if (context && !context->name().empty()) {
+ pthread_setname_np(context->name().substr(0, MAXTHREADNAMESIZE-1).c_str());
+ }
+}
+
+std::shared_ptr<LoggingContext> getLoggingContext()
+{
+ if (void* val = pthread_getspecific(getLoggingContextKey()))
+ return *((std::shared_ptr<LoggingContext>*)val);
+ return nullptr;
+}
+
+void runBody(void* Ctx)
+{
+ std::unique_ptr<std::function<void(void)>>
+ Body(reinterpret_cast<std::function<void(void)>*>(Ctx));
+ (*Body)();
+}
+
+static dispatch_queue_t getLogQueue()
+{
+ dispatch_once(&logQueueInit, ^{
+ log_queue = dispatch_queue_create("com.apple.dyld.cache.logging", DISPATCH_QUEUE_SERIAL);
+ });
+ return log_queue;
+}
+
+void setVerbose(bool level)
+{
+ verbose = level;
+}
+
+void setWarnAnErrorPrefixes(const char* warn, const char* err)
+{
+ warningPrefix = warn;
+ errorPrefix = err;
+}
+
+void setReturnNonZeroOnTerminate()
+{
+ returnNonZeroIfTerminateCalled = true;
+}
+
+void queued_print(FILE* __restrict fd, const char* str)
+{
+ const char* qstr = strdup(str);
+
+ dispatch_async(getLogQueue(), ^{
+ (void)fprintf(fd, "%s", qstr);
+ free((void*)qstr);
+ });
+}
+
+#define VLOG(header) \
+ va_list list; \
+ va_start(list, format); \
+ char temp[MAX_LOG_STR_LEN]; \
+ vsprintf(temp, format, list); \
+ auto ctx = getLoggingContext(); \
+ char temp2[MAX_LOG_STR_LEN]; \
+ if (ctx && !ctx->name().empty()) { \
+ snprintf(temp2, MAX_LOG_STR_LEN, "[%s] %s%s\n", ctx->name().c_str(), header, \
+ temp); \
+ } else { \
+ snprintf(temp2, MAX_LOG_STR_LEN, "%s%s\n", header, temp); \
+ } \
+ queued_print(stderr, temp2); \
+ va_end(list);
+
+void log(const char* __restrict format, ...)
+{
+ VLOG("");
+}
+
+void verboseLog(const char* format, ...)
+{
+ if (verbose) {
+ VLOG("");
+ }
+}
+
+static std::set<std::string> warnings;
+
+void warning(const char* format, ...)
+{
+ dispatch_once(&uniqueQueueInit, ^{
+ unique_queue = dispatch_queue_create("com.apple.dyld.cache.logging", DISPATCH_QUEUE_SERIAL);
+ });
+
+ va_list list;
+ va_start(list, format);
+ char temp[MAX_LOG_STR_LEN];
+ vsprintf(temp, format, list);
+ char* blockTemp = strdup(temp);
+
+ auto ctx = getLoggingContext();
+ if (ctx) {
+ for (auto& target : ctx->targets().second) {
+ ctx->targets().first->configurations[target.first].architectures[target.second].results.warnings.push_back(blockTemp);
+ }
+ }
+
+ dispatch_sync(unique_queue, ^{
+ if (warnings.count(blockTemp) == 0) {
+ warnings.insert(blockTemp);
+ }
+
+ free(blockTemp);
+ });
+
+ va_end(list);
+}
+
+void terminate(const char* format, ...)
+{
+ VLOG(errorPrefix);
+
+ terminateCalled = true;
+
+ if (ctx) {
+ // We are a work in a logging context, throw
+ throw std::string(temp);
+ } else {
+ // We are in general handing, let the loggging queue darain and exit
+ dispatch_sync(getLogQueue(), ^{
+ for (auto& warning : warnings) {
+ (void)fprintf(stderr, "%s%s\n", warningPrefix, warning.c_str());
+ }
+ if ( returnNonZeroIfTerminateCalled ) {
+ exit(1);
+ }
+ else {
+ time_t endtime = time(0);
+ (void)fprintf(stderr, "Finished: %s\n", asctime(localtime(&endtime)));
+ (void)fprintf(stderr, "Exiting\n");
+ exit(0);
+ }
+ });
+ }
+
+ // clang can't reason out that we won't hit this due to the dispatch_sync in the exit path
+ __builtin_unreachable();
+}
+
+void dumpLogAndExit(bool logFinishTime)
+{
+ dispatch_async(getLogQueue(), ^{
+ for (auto& warning : warnings) {
+ (void)fprintf(stderr, "%s%s\n", warningPrefix, warning.c_str());
+ }
+ if ( logFinishTime ) {
+ time_t endtime = time(0);
+ (void)fprintf(stderr, "Finished: %s\n", asctime(localtime(&endtime)));
+ (void)fprintf(stderr, "Exiting\n");
+ }
+ exit(returnNonZeroIfTerminateCalled && terminateCalled ? 1 : 0);
+ });
+}