]> git.saurik.com Git - apple/security.git/blobdiff - cdsa/cdsa_utilities/debugging.cpp
Security-177.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / debugging.cpp
index a1941e3ebde5956de3b8890dfab481d031a2893b..8a9eb25428be580e8e26379a1dd6d21cdf6da42f 100644 (file)
 #include <Security/debugsupport.h>
 #include <Security/globalizer.h>
 #include <cstdarg>
+#include <ctype.h>
 
 #define SYSLOG_NAMES   // compile syslog name tables
 #include <syslog.h>
 
-namespace Security {
-namespace Debug {
+#include <cxxabi.h>    // for name demangling
 
+// enable kernel tracing
+#define ENABLE_SECTRACE 1
 
-#if !defined(NDEBUG)
+
+namespace Security {
+namespace Debug {
 
 
 //
@@ -38,7 +42,7 @@ namespace Debug {
 //
 void debug(const char *scope, const char *format, ...)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
        va_list args;
        va_start(args, format);
        Target::get().message(scope, format, args);
@@ -48,24 +52,14 @@ void debug(const char *scope, const char *format, ...)
 
 void vdebug(const char *scope, const char *format, va_list args)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
     Target::get().message(scope, format, args);
 #endif
 }
 
-void Scope::operator () (const char *format, ...)
-{
-#if !defined(NDEBUG_STUBS)
-       va_list args;
-       va_start(args, format);
-       Target::get().message(mScope, format, args);
-       va_end(args);
-#endif
-}
-
 bool debugging(const char *scope)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
        return Target::get().debugging(scope);
 #else
     return false;
@@ -73,6 +67,28 @@ bool debugging(const char *scope)
 }
 
 
+//
+// 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
 //
@@ -87,7 +103,7 @@ bool dumping(const char *scope)
 
 void dump(const char *format, ...)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
        va_list args;
        va_start(args, format);
        Target::get().dump(format, args);
@@ -97,7 +113,7 @@ void dump(const char *format, ...)
 
 void dumpData(const void *ptr, size_t size)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
        const char *addr = reinterpret_cast<const char *>(ptr);
        const char *end = addr + size;
        bool isText = true;
@@ -112,14 +128,14 @@ void dumpData(const void *ptr, size_t size)
        } else {
                dump("0x");
                for (const char *p = addr; p < end; p++)
-                       dump("%2.2x", *p);
+                       dump("%2.2x", static_cast<unsigned char>(*p));
        }
 #endif //NDEBUG_STUBS
 }
 
 void dumpData(const char *title, const void *ptr, size_t size)
 {
-#if !defined(NDEBUG_STUBS)
+#if !defined(NDEBUG_CODE)
        dump("%s: ", title);
        dumpData(ptr, size);
        dump("\n");
@@ -127,16 +143,39 @@ void dumpData(const char *title, const void *ptr, size_t size)
 }
 
 
+//
+// 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_STUBS)
+#if !defined(NDEBUG_CODE)
 
-Target::Target() : showScope(false), showThread(false),        showPid(false), sink(NULL)
+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()
@@ -188,7 +227,12 @@ bool Target::debugging(const char *scope)
 //
 void Target::dump(const char *format, va_list args)
 {
-       sink->dump(format, 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)
@@ -196,6 +240,7 @@ bool Target::dump(const char *scope)
        return dumpSelector(scope);
 }
 
+
 //
 // Selector objects.
 //
@@ -363,13 +408,27 @@ Target &Target::get()
 Target::Sink::~Sink()
 { }
 
-void Target::Sink::dump(const char *, va_list)
+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)
 //
@@ -388,18 +447,21 @@ void FileSink::put(const char *buffer, unsigned int)
        putc('\n', file);
 }
 
-void FileSink::dump(const char *format, va_list args)
+void FileSink::dump(const char *text)
 {
        StLock<Mutex> locker(lock, false);
        if (lockIO)
                locker.lock();
-       vfprintf(file, format, args);
+       fputs(text, file);
 }
 
 void FileSink::configure(const char *options)
 {
-       if (options == NULL || !strstr(options, "noflush"))
+       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");
@@ -415,10 +477,10 @@ void SyslogSink::put(const char *buffer, unsigned int)
        syslog(priority, "%s", buffer);
 }
 
-void SyslogSink::dump(const char *format, va_list args)
+void SyslogSink::dump(const char *text)
 {
        // add to dump buffer
-       vsnprintf(dumpPtr, dumpBuffer + dumpBufferSize - dumpPtr, format, args);
+       snprintf(dumpPtr, dumpBuffer + dumpBufferSize - dumpPtr, "%s", text);
        
        // take off full lines and submit
        char *p = dumpBase;
@@ -445,11 +507,21 @@ void SyslogSink::configure(const char *options)
 {
 }
 
-#endif //NDEBUG_STUBS
+#endif //NDEBUG_CODE
+
+
+//
+// kernel tracing support (C version)
+//
+extern "C" void security_ktrace(int);
 
-#endif // NDEBUG
+void security_ktrace(int code)
+{
+#if defined(ENABLE_SECTRACE)
+       syscall(180, code, 0, 0, 0, 0);
+#endif
+}
 
 
 } // end namespace Debug
-
 } // end namespace Security