X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/ed6778a32ecff23bc2dfb6ca452badd0c68774a0..563f4f96f568bcdc0a04a82f89cafe3bebbe43f1:/cdsa/cdsa_utilities/debugging.cpp diff --git a/cdsa/cdsa_utilities/debugging.cpp b/cdsa/cdsa_utilities/debugging.cpp deleted file mode 100644 index 8a9eb254..00000000 --- a/cdsa/cdsa_utilities/debugging.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -// -// debugging - non-trivial debugging support -// -#include -#include -#include -#include - -#define SYSLOG_NAMES // compile syslog name tables -#include - -#include // for name demangling - -// enable kernel tracing -#define ENABLE_SECTRACE 1 - - -namespace Security { -namespace Debug { - - -// -// Main debug functions (global and in-scope) -// -void debug(const char *scope, const char *format, ...) -{ -#if !defined(NDEBUG_CODE) - va_list args; - va_start(args, format); - Target::get().message(scope, format, args); - va_end(args); -#endif -} - -void vdebug(const char *scope, const char *format, va_list args) -{ -#if !defined(NDEBUG_CODE) - Target::get().message(scope, format, args); -#endif -} - -bool debugging(const char *scope) -{ -#if !defined(NDEBUG_CODE) - return Target::get().debugging(scope); -#else - return false; -#endif -} - - -// -// C equivalents for some basic uses -// -extern "C" { - int __security_debugging(const char *scope); - void __security_debug(const char *scope, const char *format, ...); -}; - -int __security_debugging(const char *scope) -{ return debugging(scope); } - -void __security_debug(const char *scope, const char *format, ...) -{ -#if !defined(NDEBUG_CODE) - va_list args; - va_start(args, format); - vdebug(scope, format, args); - va_end(args); -#endif -} - - -// -// Dump facility -// -bool dumping(const char *scope) -{ -#if defined(NDEBUG_STUBS) - return false; -#else - return Target::get().dump(scope); -#endif -} - -void dump(const char *format, ...) -{ -#if !defined(NDEBUG_CODE) - va_list args; - va_start(args, format); - Target::get().dump(format, args); - va_end(args); -#endif -} - -void dumpData(const void *ptr, size_t size) -{ -#if !defined(NDEBUG_CODE) - const char *addr = reinterpret_cast(ptr); - const char *end = addr + size; - bool isText = true; - for (const char *p = addr; p < end; p++) - if (!isprint(*p)) { isText = false; break; } - - if (isText) { - dump("\""); - for (const char *p = addr; p < end; p++) - dump("%c", *p); - dump("\""); - } else { - dump("0x"); - for (const char *p = addr; p < end; p++) - dump("%2.2x", static_cast(*p)); - } -#endif //NDEBUG_STUBS -} - -void dumpData(const char *title, const void *ptr, size_t size) -{ -#if !defined(NDEBUG_CODE) - dump("%s: ", title); - dumpData(ptr, size); - dump("\n"); -#endif //NDEBUG_STUBS -} - - -// -// Turn a C++ typeid into a nice type name. -// This uses the C++ ABI where available. -// We're stripping out a few C++ prefixes; they're pretty redundant (and obvious). -// -string makeTypeName(const type_info &type) -{ - int status; - char *cname = abi::__cxa_demangle(type.name(), NULL, NULL, &status); - string name = !strncmp(cname, "Security::", 10) ? (cname + 10) : - !strncmp(cname, "std::", 5) ? (cname + 5) : - cname; - ::free(cname); // yes, really (ABI rules) - return name; -} - - -// -// Target initialization -// -#if !defined(NDEBUG_CODE) - -Target::Target() - : showScope(false), showThread(false), showPid(false), - sink(NULL) -{ - // put into singleton slot if first - if (singleton == NULL) - singleton = this; - - // insert terminate handler - if (!previousTerminator) // first time we do this - previousTerminator = set_terminate(terminator); -} - -Target::~Target() -{ -} - - -// -// The core logging function of a Target -// -void Target::message(const char *scope, const char *format, va_list args) -{ - if (logSelector(scope)) { - // note: messageConstructionSize is big enough for all prefixes constructed - char buffer[messageConstructionSize]; // building the message here - char *bufp = buffer; - if (showScope && scope) { // add "scope " - if (const char *sep = strchr(scope, ',')) { - bufp += sprintf(bufp, "%-*s", Name::maxLength, (const char *)Name(scope, sep)); - } else { // single scope - bufp += sprintf(bufp, "%-*s", Name::maxLength, scope); - } - } - if (showPid) { // add "[Pid] " - bufp += sprintf(bufp, "[%d] ", getpid()); - } - if (showThread) { // add "#Tthreadid " - *bufp++ = '#'; - Thread::Identity::current().getIdString(bufp); - bufp += strlen(bufp); - *bufp++ = ' '; - } - vsnprintf(bufp, buffer + sizeof(buffer) - bufp, format, args); - for (char *p = bufp; *p; p++) - if (!isprint(*p)) - *p = '?'; - sink->put(buffer, bufp - buffer); - } -} - -bool Target::debugging(const char *scope) -{ - return logSelector(scope); -} - - -// -// The core debug-dump function of a target -// -void Target::dump(const char *format, va_list args) -{ - char buffer[messageConstructionSize]; // building the message here - vsnprintf(buffer, sizeof(buffer), format, args); - for (char *p = buffer; *p; p++) - if (!isprint(*p) && !isspace(*p) || *p == '\r') - *p = '?'; - sink->dump(buffer); -} - -bool Target::dump(const char *scope) -{ - return dumpSelector(scope); -} - - -// -// Selector objects. -// -Target::Selector::Selector() : useSet(false), negate(false) -{ } - -void Target::Selector::operator = (const char *scope) -{ - if (scope) { - // initial values - if (!strcmp(scope, "all")) { - useSet = false; - negate = true; - } else if (!strcmp(scope, "none")) { - useSet = negate = false; - } else { - useSet = true; - enableSet.erase(enableSet.begin(), enableSet.end()); - if (scope[0] == '-') { - negate = true; - scope++; - } else - negate = false; - while (const char *sep = strchr(scope, ',')) { - enableSet.insert(Name(scope, sep)); - scope = sep + 1; - } - enableSet.insert(scope); - } - } else { - useSet = negate = false; - } -} - -bool Target::Selector::operator () (const char *scope) const -{ - // a scope of NULL is a special override; it always qualifies - if (scope == NULL) - return true; - - if (useSet) { - while (const char *sep = strchr(scope, ',')) { - if (enableSet.find(Name(scope, sep)) != enableSet.end()) - return !negate; - scope = sep + 1; - } - return (enableSet.find(scope) != enableSet.end()) != negate; - } else { - return negate; - } -} - - -// -// Establish Target state from the environment -// -void Target::setFromEnvironment() -{ - // set scopes - logSelector = getenv("DEBUGSCOPE"); - dumpSelector = getenv("DEBUGDUMP"); - - // - // Set and configure destination. Currently available: - // /some/where -> that file - // LOG_SOMETHING -> syslog facility - // >&number -> that (already) open file descriptor - // anything else -> try as a filename sight unseen - // DEBUGDEST not set -> stderr - // anything in error -> stderr (with an error message on it) - // - if (const char *dest = getenv("DEBUGDEST")) { - if (dest[0] == '/') { // full pathname, write to file - to(dest); - } else if (!strncmp(dest, "LOG_", 4)) { // syslog - int facility = LOG_DAEMON; - for (CODE *cp = facilitynames; cp->c_name; cp++) - if (!strcmp(dest, cp->c_name)) - facility = cp->c_val; - to(facility | LOG_DEBUG); - } else if (!strncmp(dest, ">&", 2)) { // to file descriptor - int fd = atoi(dest+2); - if (FILE *f = fdopen(fd, "a")) { - to(f); - } else { - to(stderr); - ::debug(NULL, "cannot log to fd[%d]: %s", fd, strerror(errno)); - } - } else { // if everything else fails, write a file - to(dest); - } - } else { // default destination is stderr - to(stderr); - } - configure(); -} - - -void Target::configure() -{ - configure(getenv("DEBUGOPTIONS")); -} - -void Target::configure(const char *config) -{ - // configure global options - showScope = config && strstr(config, "scope"); - showThread = config && strstr(config, "thread"); - showPid = config && strstr(config, "pid"); - - // configure sink - if (sink) - sink->configure(config); -} - - -// -// Explicit destination assignments -// -void Target::to(Sink *s) -{ - delete sink; - sink = s; -} - -void Target::to(FILE *file) -{ - to(new FileSink(file)); -} - -void Target::to(const char *filename) -{ - if (FILE *f = fopen(filename, "a")) { - to(new FileSink(f)); - } else { - to(stderr); - ::debug(NULL, "cannot debug to \"%s\": %s", filename, strerror(errno)); - } -} - -void Target::to(int syslogPriority) -{ - to(new SyslogSink(syslogPriority)); -} - - -// -// Making and retrieving the default singleton -// -Target *Target::singleton; - -Target &Target::get() -{ - if (singleton == NULL) { - Target *t = new Target; - t->setFromEnvironment(); - } - return *singleton; -} - - -// -// Standard sink implementations -// -Target::Sink::~Sink() -{ } - -void Target::Sink::dump(const char *) -{ } - -void Target::Sink::configure(const char *) -{ } - - -// -// The terminate handler installed when a Target is created -// -terminate_handler Target::previousTerminator; - -void Target::terminator() -{ - debug("exception", "uncaught exception terminates program"); - previousTerminator(); - debug("exception", "prior termination handler failed to abort; forcing abort"); - abort(); -} - - -// -// File sinks (write to file via stdio) -// -void FileSink::put(const char *buffer, unsigned int) -{ - StLock locker(lock, false); - if (lockIO) - locker.lock(); - if (addDate) { - time_t now = time(NULL); - char *date = ctime(&now); - date[19] = '\0'; - fprintf(file, "%s ", date + 4); // Nov 24 18:22:48 - } - fputs(buffer, file); - putc('\n', file); -} - -void FileSink::dump(const char *text) -{ - StLock locker(lock, false); - if (lockIO) - locker.lock(); - fputs(text, file); -} - -void FileSink::configure(const char *options) -{ - if (options == NULL || !strstr(options, "noflush")) { - // we mean "if the file isn't unbuffered", but what's the portable way to say that? - if (file != stderr) - setlinebuf(file); - } - if (options) { - addDate = strstr(options, "date"); - lockIO = !strstr(options, "nolock"); - } -} - - -// -// Syslog sinks (write to syslog) -// -void SyslogSink::put(const char *buffer, unsigned int) -{ - syslog(priority, "%s", buffer); -} - -void SyslogSink::dump(const char *text) -{ - // add to dump buffer - snprintf(dumpPtr, dumpBuffer + dumpBufferSize - dumpPtr, "%s", text); - - // take off full lines and submit - char *p = dumpBase; - while (char *q = strchr(p, '\n')) { - *q++ = '\0'; // terminate/break - syslog(priority, " @@ %s", p); - p = q; - } - - if (*p) { // left-over unterminated line segment in buffer - dumpPtr = p + strlen(p); - if ((dumpBase = p) > dumpBuffer + dumpBufferSize / 2) { - // shift buffer down to make room - memmove(dumpBuffer, dumpBase, dumpPtr - dumpBase); - dumpPtr -= (dumpBase - dumpBuffer); - dumpBase = dumpBuffer; - } - } else { // buffer is empty; reset to start - dumpBase = dumpPtr = dumpBuffer; - } -} - -void SyslogSink::configure(const char *options) -{ -} - -#endif //NDEBUG_CODE - - -// -// kernel tracing support (C version) -// -extern "C" void security_ktrace(int); - -void security_ktrace(int code) -{ -#if defined(ENABLE_SECTRACE) - syscall(180, code, 0, 0, 0, 0); -#endif -} - - -} // end namespace Debug -} // end namespace Security