Windows software trace preprocessor

Last updated

The Windows software trace preprocessor (WPP; the preprocessor and related support tools are known as WPP Software Tracing) is a preprocessor that simplifies the use of WMI event tracing to implement efficient software tracing in drivers and applications that target Windows 2000 and later operating systems. WPP was created by Microsoft and is included in the Windows DDK. Although WPP is wide in its applicability, it is not included in the Windows SDK, and therefore is primarily used for drivers and driver support software produced by software vendors that purchase the Windows DDK.

Microsoft Windows is a group of several graphical operating system families, all of which are developed, marketed, and sold by Microsoft. Each family caters to a certain sector of the computing industry. Active Windows families include Windows NT and Windows Embedded; these may encompass subfamilies, e.g. Windows Embedded Compact or Windows Server. Defunct Windows families include Windows 9x, Windows Mobile and Windows Phone.

In computer science, a preprocessor is a program that processes its input data to produce output that is used as input to another program. The output is said to be a preprocessed form of the input data, which is often used by some subsequent programs like compilers. The amount and kind of processing done depends on the nature of the preprocessor; some preprocessors are only capable of performing relatively simple textual substitutions and macro expansions, while others have the power of full-fledged programming languages.

Windows Management Instrumentation (WMI) consists of a set of extensions to the Windows Driver Model that provides an operating system interface through which instrumented components provide information and notification. WMI is Microsoft's implementation of the Web-Based Enterprise Management (WBEM) and Common Information Model (CIM) standards from the Distributed Management Task Force (DMTF).

Contents

Background

Software tracing is a specialized use of logging to record information about a program's execution. This information is commonly used for debugging. In contrast to event logging, the primary purpose of which is to produce records of events that can be audited by system administrators (see for example Event Viewer ) or analyzed by management tools, software tracing is primarily a debugging aid for software developers. As such, many of the non-functional requirements of event logging, such as localizability or a standards-based output format, are explicitly non-goals for most applications of software tracing. On the other hand, software tracing has special requirements for performance that are not generally as important in event logging. For example, one common use of software tracing, in/out tracing, produces output at the entry point and return of functions or methods so that a developer can visually follow the execution path, often including parameters and return values, in a debugger or text-based log file (this can be seen as a run-time analog of a sequence diagram). This type of tracing, although useful for developers, can greatly hurt performance of a software product if it cannot be disabled (either at compile-time via conditional compilation, or at run-time via flags).

Debugging is the process of finding and resolving defects or problems within a computer program that prevent correct operation of computer software or a system.

System administrator person who maintains and operates a computer system and/or network

A system administrator, or sysadmin, is a person who is responsible for the upkeep, configuration, and reliable operation of computer systems; especially multi-user computers, such as servers. The system administrator seeks to ensure that the uptime, performance, resources, and security of the computers they manage meet the needs of the users, without exceeding a set budget when doing so.

Event Viewer

Event Viewer is a component of Microsoft's Windows NT line of operating systems that lets administrators and users view the event logs on a local or remote machine. In Windows Vista, Microsoft overhauled the event system.

Additional considerations special to software tracing include the following:

Proprietary software, also known as "closed-source software", is a non-free computer software for which the software's publisher or another person retains intellectual property rights—usually copyright of the source code, but sometimes patent rights.

In computing, source code is any collection of code, possibly with comments, written using a human-readable programming language, usually as plain text. The source code of a program is specially designed to facilitate the work of computer programmers, who specify the actions to be performed by a computer mostly by writing source code. The source code is often transformed by an assembler or compiler into binary machine code understood by the computer. The machine code might then be stored for execution at a later time. Alternatively, source code may be interpreted and thus immediately executed.

Due to the first two considerations, traditional methods of software tracing use conditional compilation to enable or disable tracing (and inclusion of tracing data) at compile-time. For example, using the C preprocessor, one might define a macro DebugOut as follows:

The C preprocessor or cpp is the macro preprocessor for the C and C++ computer programming languages. The preprocessor provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control.

#ifdef _DEBUG #define DebugOut(msg, ...) \     DebugPrintf(__FUNCTION__ "(" __FILE__ ":" TO_STRING(__LINE__) ")\t" \         msg, __VAR_ARGS__) #else #define DebugOut(msg, ...) #endif

where TO_STRING is a macro that converts the line number (__LINE__) to a string and DebugPrintf is a printf-like function that might for example output text to the debugger.

Then, the following code:

DebugOut("Error %d occurred\n", error_code);

would produce output similar to the following on debug builds only:

SomeFunction(file.c:78)    Error 217 occurred

Another technique for certain types of tracing (particularly in/out tracing) is to use instrumentation. While this technique can address many of the major concerns, it is not always available (typically only in managed code).

In the context of computer programming, instrumentation refers to an ability to monitor or measure the level of a product's performance, to diagnose errors, and to write trace information. Programmers implement instrumentation in the form of code instructions that monitor specific components in a system. When an application contains instrumentation code, it can be managed by using a management tool. Instrumentation is necessary to review the performance of the application. Instrumentation approaches can be of two types: source instrumentation and binary instrumentation.

Managed code is computer program code that requires and will execute only under the management of a Common Language Runtime (CLR) virtual machine, e.g. .NET Core, .NET Framework, or Mono. The term was coined by Microsoft.

WMI event tracing is an example of a technology that addresses in particular performance of tracing in performance-critical code such as drivers. It can also address the concern of controlling the distribution of sensitive trace information by letting a developer define the human-readable tracing data ("Error %d occurred\n" in the example above) separately from the code so that it is not built into the product (in the code, a specific message is referred to by its message number). However, there are some important limitations:

Operation of WPP

WPP is run prior to compilation (in other words, before even the C preprocessor), and generates a trace message header for each file that it processes (by default this header is filename.tmh, where filename is the name of the processed source file). This header must then be explicitly included into the source file, for example:

// File: file.cxx // This file is an example of using WPP #include "file.tmh"

WPP's understanding of C/C++ syntax is very limited. In particular, it does not expand macros (except in special circumstances where it is necessary), nor does it handle pragmas or perform any semantic analysis.

A developer specifies one or more tracing macros that WPP should handle, via a configuration file, special annotations in comments, command line parameters, or some combination of these methods. Each time WPP encounters one of the macros that it is supposed to handle, it generates a trace message macro. In other words, if for example DoTrace is a tracing macro, WPP will generate a separate macro for each occurrence of DoTrace. The generated trace message macros are disambiguated by file name and line number, and, using various preprocessor tricks, WPP in turn defines the original tracing macro so that it will expand the appropriate trace message macro at each occurrence.

How trace message macros are generated by WPP depends on a template file (the format of the file is undocumented). The default template files included with WPP specify that the string of a trace message should be included in an annotation (using the __annotation feature of the Microsoft Compiler). These strings are not included in the compiled code, but are included in the debugger symbol file in a format that tools included with WPP can understand. The trace message macros also include the logic for enabling or disabling tracing via flags and the calls to WMI event tracing APIs.

Limitations

#define CheckForErrors(error_code) \     if (IsError(error_code)) \     { \         DoTrace("Error %d occurred\n", err); \         HandleError(error_code); \     }

then WPP will not generate the trace message macros for DoTrace where CheckForErrors occurs. WPP provides an ad hoc workaround for this issue, but there still exists a small class of macros that cannot be expressed even using the workaround.

Related Research Articles

Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class to work on many different data types without being rewritten for each one.

GNU Autoconf is a tool for producing configure scripts for building, installing and packaging software on computer systems where a Bourne shell is available.

In computer programming, an assertion is a statement that a predicate is always true at that point in code execution. It can help a programmer read the code, help a compiler compile it, or help the program detect its own defects.

A variadic macro is a feature of some computer programming languages, especially the C preprocessor, whereby a macro may be declared to accept a varying number of arguments.

In computing, syslog is a standard for message logging. It allows separation of the software that generates messages, the system that stores them, and the software that reports and analyzes them. Each message is labeled with a facility code, indicating the software type generating the message, and assigned a severity level.

In the C and C++ programming languages, an #include guard, sometimes called a macro guard or header guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive.

Log4j java library for logging

Apache Log4j is a Java-based logging utility. It was originally written by Ceki Gülcü and is part of the Apache Logging Services project of the Apache Software Foundation. Log4j is one of several Java logging frameworks.

In the C and C++ programming languages, #pragma once is a non-standard but widely supported preprocessor directive designed to cause the current source file to be included only once in a single compilation. Thus, #pragma once serves the same purpose as include guards, but with several advantages, including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.

assert.h is a header file in the standard library of the C programming language that defines the C preprocessor macro assert . In C++ it is also available through the <cassert> header file.

In software engineering, tracing involves a specialized use of logging to record information about a program's execution. This information is typically used by programmers for debugging purposes, and additionally, depending on the type and detail of information contained in a trace log, by experienced system administrators or technical-support personnel and by software monitoring tools to diagnose common problems with software. Tracing is a cross-cutting concern.

In C and C++ programming language terminology, a translation unit is the ultimate input to a C or C++ compiler from which an object file is generated. In casual usage it is sometimes referred to as a compilation unit. A translation unit roughly consists of a source file after it has been processed by the C preprocessor, meaning that header files listed in #include directives are literally included, sections of code within #ifndef may be included, and macros have been expanded.

Nemerle is a general-purpose high-level statically typed programming language designed for platforms using the Common Language Infrastructure (.NET/Mono). It offers functional, object-oriented (OO) and imperative features. It has a simple C#-like syntax and a powerful metaprogramming system. In June 2012, the core developers of Nemerle were hired by the Czech software development company JetBrains. The team is focusing on developing Nitra, a framework to implement extant and new programming languages. This framework will likely be used to create future versions of Nemerle.

A macro in computer science is a rule or pattern that specifies how a certain input sequence should be mapped to a replacement input sequence according to a defined procedure.

X Macros are a technique for reliable maintenance of parallel lists, of code or data, whose corresponding items must appear in the same order. They are most useful where at least some of the lists cannot be composed by indexing, such as compile time.

Objective-C is a general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language. It was the main programming language supported by Apple for the macOS and iOS operating systems, and their respective application programming interfaces (APIs) Cocoa and Cocoa Touch until the introduction of Swift. The programming language Objective-C was originally developed in the early 1980s. It was selected as the main language used by NeXT for its NeXTSTEP operating system, from which macOS and iOS are derived. Portable Objective-C programs that do not use the Cocoa or Cocoa Touch libraries, or those using parts that may be ported or reimplemented for other systems, can also be compiled for any system supported by GNU Compiler Collection (GCC) or Clang.