C and C++ Binaries

Writing C++ Plug-Ins For CodeSonar

This section describes how to write and install C++ plug-ins for CodeSonar.

CodeSonar SaaS Note: If you want to use your own custom plug-ins with CodeSonar SaaS, contact CodeSecure support for assistance. The installation instructions provided in this page are not sufficient to make plug-ins available to SaaS analyses.



Overview

To create and use a CodeSonar C++ plug-in, do the following:

  1. Create C++ source file(s) for the plug-in.
  2. Compile the plug-in into a library: .dll, .so, or .bundle as appropriate for your platform.
  3. Save the plug-in in directory $CSONAR/codesonar/plugins, where $CSONAR is the CodeSonar installation directory.

Create Source File(s)

Suppose you want to define a plug-in called pname_plugin.

File content requirements The C++ source file(s) for the plug-in must include the following elements.
#define CS_CPP_IMPL             // must precede #include "csonar_api.hpp"
#include "csonar_api.hpp"       // uses the 'cs' namespace  
// ...
static void cs_plug_main(void){}// must be present but can be empty
CS_DEFINE_PLUGIN(pname_plugin)  // must be final line; built plug-in library must have corresponding name
File name requirements Source file: none
Built library: must correspond to the name registered with CS_DEFINE_PLUGIN(pname_plugin) in the source file:
Windows: pname_plugin.dll
All other systems: pname_plugin.so
Add visitors In top-level scope, or in cs_plug_main().
Define new warning classes;
define new metric classes
In top-level scope, or in cs_plug_main().
Key API Classes analysis, visitor, warningclass, project_metricclass, compunit_metricclass, sfile_metricclass, procedure_metricclass.
Annotated Examples Classes Plug-in Tutorial: C++, AST Tutorial: C++

(Further implementation notes are provided below.)

Compile the Plug-In

Once the plug-in source files are created, compile the plug-in into a library. The library name must meet the file name requirements listed above.

Preliminaries

There are two important requirements for building a C++ plug-in.

Performing the Compilation

Compilation instructions vary slightly depending on your operating system.

  Compiler Command Line Notes
Windows
  cl
cl /LD /MD /EHsc "/I%CSONAR%\codesonar\include"
"/I%CSONAR%\csurf\include" pname_plugin.cpp
"%CSONAR%\codesonar\lib\codesonar.lib"
Cygwin g++ Note: Cygwin g++ is only suitable for building 32-bit CodeSonar plugins. Cygwin g++ only builds Cygwin binaries, so is not suitable for building CodeSonar plug-ins. If you do not have an alternative g++, you will need to download and install one. One option is mingw-w64.
  • Cygwin 1.7 Use the g++-3 executable (not g++ / g++-4, which does not support -mno-cygwin). If you do not have a g++-3 binary, use Cygwin's setup.exe tool to install the mingw-g++ component.
    g++-3 -shared -mno-cygwin "-I$CSONAR/codesonar/include"
    "-I$CSONAR/csurf/include" pname_plugin.cpp -o pname_plugin.dll
    "-L$CSONAR/codesonar/lib" -lcodesonar
  • Cygwin 1.5
    g++ -shared -mno-cygwin "-I$CSONAR/codesonar/include"
    "-I$CSONAR/csurf/include" pname_plugin.cpp -o pname_plugin.dll
    "-L$CSONAR/codesonar/lib" -lcodesonar
  • Link against $CSONAR/codesonar/lib/libcodesonar.a
  • Use the -mno-cygwin flag.
  • If you are using 32-bit CodeSonar on a 64-bit platform, add the -m32 flag to the command line (unless your compiler version will not accept it).
MinGW g++
g++ -shared "-I$CSONAR/codesonar/include"
"-I$CSONAR/csurf/include" pname_plugin.cpp -o pname_plugin.dll
"-L$CSONAR/codesonar/lib" -lcodesonar
  • Link against $CSONAR/codesonar/lib/libcodesonar.a
  • If you are using 64-bit CodeSonar, use 64-bit MinGW g++. Note that, depending on your system configuration, this may not be the version invoked by the 'g++' command - in this case you will need to either adjust your environment or use a different name to invoke the correct compiler.
  • If you are using 32-bit CodeSonar on a 64-bit platform, add the -m32 flag to the command line (unless your g++ version will not accept it).
otherwise
  • Refer to your compiler documentation to see how to create an import library from
    $CSONAR/codesonar/lib/codesonar.def
    (or have your plugin obtain the necessary function pointers with GetProcAddress).
  • Build pname_plugin.dll from pname_plugin.cpp, linking against this import library and including $CSONAR/codesonar/include and $CSONAR/csurf/include.
  • [64-bit CodeSonar only] A useful starting place for Visual Studio users is How to: Configure Visual C++ Projects to Target 64-Bit Platforms.
All Other Systems
We provide a full example for g++. For other compilers, build pname_plugin.so from pname_plugin.cpp, including $CSONAR/codesonar/include and $CSONAR/csurf/include.
  g++
g++ -fPIC -shared -o pname_plugin.so pname_plugin.cpp
-I$CSONAR/codesonar/include
-I$CSONAR/csurf/include
  • Use the -fPIC flag.
  • If you are using 32-bit CodeSonar on a 64-bit platform, add the -m32 flag to the command line (unless it causes problems).

Troubleshooting

If the build fails and reports errors in cs_basic_types.h, this generally indicates that your build has a different pointer width than that of the CodeSonar installation. If this happens:

  1. Double-check the "Host Platform" line in $CSONAR/SIGNATURE.txt to make sure you know the pointer width for your CodeSonar installation
  2. Make sure your build command has the same pointer width.
    In particular, make sure you have applied any build flags or other adjustments indicated in Performing the Compilation (above). Depending on your compiler, you may need to perform additional steps: consult your compiler documentation for details.

Install

Save the plug-in in directory $CSONAR/codesonar/plugins, where $CSONAR is the CodeSonar installation directory. The plug-in will be automatically loaded and run when CodeSonar runs.

If you want to save the plug-in in a different location, use the PLUGINS configuration file option to specify its file path so that CodeSonar can load and run it.

Note: you will not be able to modify plug-in .dll files in $CSONAR/codesonar/plugins, or .dll files specified by the PLUGINS option, while a CodeSonar process is running. If you encounter this problem while trying to update an existing plug-in, use the Windows Task Manager (or a similar tool) to end all codesonar.exe processes.

Implementation Notes

Adding Visitors

Add visitors in the top-level scope of the plug-in, or in cs_plug_main().
Adding: all visitors except step visitors
  1. Subclass visitor to characterize your visitor.
  2. Create an object of the subclass.
  3. Pass the object to the appropriate analysis::add_*_visitor() method.
Adding: step visitors
  1. Subclass step_state to characterize your step visitor.
  2. Create an object of the subclass.
  3. Pass the object to analysis::add_step_bottom_up_visitor().

The following table lists the available methods for adding visitors.

Build/Analysis Phase Add visitors with
drop traversal analysis::add_project_drop_visitor()
analysis::add_compunit_drop_visitor()
analysis::add_procedure_drop_visitor()
analysis::add_global_symbol_drop_visitor()
analysis::add_project_drop_finish_visitor()
after drop traversal, before anything else (do setup work in top level scope of plug-in)
after setup visitors, before serial depth-first analysis phase analysis::add_project_visitor()
serial depth-first analysis phase analysis::add_compunit_visitor()
analysis::add_sfile_visitor()
analysis::add_sfileinst_visitor()
analysis::add_sfileinst_finish_visitor()
analysis::add_sfile_finish_visitor()
analysis::add_procedure_visitor()
analysis::add_point_visitor()
analysis::add_symbol_visitor()
analysis::add_procedure_finish_visitor()
analysis::add_compunit_finish_visitor()
after serial depth-first analysis phase, before any program parallel visitors analysis::add_project_finish_visitor()
after program finish visitors, before parallel depth-first analysis phase analysis::add_project_parallel_visitor()
parallel depth-first analysis phase analysis::add_compunit_parallel_visitor()
analysis::add_sfile_parallel_visitor()
analysis::add_sfileinst_parallel_visitor()
analysis::add_sfileinst_parallel_finish_visitor()
analysis::add_sfile_parallel_finish_visitor()
analysis::add_procedure_parallel_visitor()
analysis::add_point_parallel_visitor()
analysis::add_symbol_parallel_visitor()
analysis::add_procedure_parallel_finish_visitor()
analysis::add_compunit_parallel_finish_visitor()
after parallel depth-first analysis phase, before any program bottom-up visitors analysis::add_project_parallel_finish_visitor()
after pointer analysis phase, before bottom up analysis phase analysis::add_project_bottom_up_visitor()
bottom-up analysis phase analysis::add_procedure_bottom_up_visitor()
analysis::add_point_bottom_up_visitor()
analysis::add_step_bottom_up_visitor()
analysis::add_procedure_bottom_up_finish_visitor()
after bottom-up phase (all traversal is finished) analysis::add_project_bottom_up_finish_visitor()
(periodically, as analysis progresses) analysis::add_cache_cleanup_visitor

New Warning Classes

Warning class type warningclass
Warning class flag type warningclass_flags
Must be defined in the top-level scope of the plug-in, or in cs_plug_main().
Defined with analysis::create_warningclass()

Issuing Warnings

Issue warnings with one of the following.

Both methods are overloaded to account for all warning-issuing cases. See the warningclass class description for details.

Retracting Warnings

Retraction info parameter type (when warning reported) warning_retraction_info
Manually retract with warning::retract()

Warning Class Information

Warning Class Information Method
ID (a numeric identifier) warningclass::id()
Name warningclass::name()
Are WARNING_FILTER settings such that instances of this warning class will always be ignored? warningclass::always_discarded()
Retrieve class by ID or name. analysis::lookup_warningclass() (overloaded)

New Metric Classes

Metric class type project_metricclass
compunit_metricclass
sfile_metricclass
procedure_metricclass
Metric class flag type metricclass_flags
Must be defined in the top-level scope of the plug-in, or in cs_plug_main().
Defined with The create() method of the metric class manager with the corresponding granularity:
project_metricclass_manager::create()

compunit_metricclass_manager::create()
sfile_metricclass_manager::create()
procedure_metricclass_manager::create()

Reporting and Retracting Metric Values

Automatically-reported metrics are computed and reported automatically by the CodeSonar analysis. Manually-reported metrics must be reported explicitly by the plug-in.

Both automatic and manual retraction can take place.

Manually report with The metric class report() method.
project_metricclass::report()

compunit_metricclass::report()
sfile_metricclass::report()
procedure_metricclass::report()
Manually retract with The metric class retract() method.
compunit_metricclass::retract()
sfile_metricclass::retract()
procedure_metricclass::retract()
(All analysis-granularity metrics are automatically retracted.)

Other Metric Functionality

Functionality Metric Class Method Links
Get the granularity of a metric class. none: granularity is implicit in type of metric class object. -
Get the tag (short identifier) of a metric class. tag() project_metricclass::tag()
compunit_metricclass::tag()
sfile_metricclass::tag()
procedure_metricclass::tag()
Get the description (longer, human readable description) of a metric class. description() project_metricclass::description()
compunit_metricclass::description()
sfile_metricclass::description()
procedure_metricclass::description()
Get the flags associated with a metric class. flags() project_metricclass::flags()
compunit_metricclass::flags()
sfile_metricclass::flags()
procedure_metricclass::flags()
Look up a metric class. lookup() project_metricclass_manager::lookup()
compunit_metricclass_manager::lookup()
sfile_metricclass_manager::lookup()
procedure_metricclass_manager::lookup()
Get the value of a specified metric for a specified program element. value() project_metricclass::value()
compunit_metricclass::value()
sfile_metricclass::value()
procedure_metricclass::value()
Iterate over all metric classes with a specified granularity. metricclasses() project_metricclass_manager::metricclasses()
compunit_metricclass_manager::metricclasses()
sfile_metricclass_manager::metricclasses()
procedure_metricclass_manager::metricclasses()

More on Plug-Ins

General Information:

Visitors Plug-ins are based on visitors, which specify actions to be carried out on elements of the CodeSonar internal representation (IR) at various stages of the analysis.
Writing Plug-Ins General information about creating plug-ins to attach custom functionality to the CodeSonar analysis.
Custom Checks: Accounting for Incrementality Ensuring that custom checks implemented in plug-ins generate appropriate results in incremental analyses.
Plug-In Tutorial Two annotated example plug-ins (each provided in all API languages), with building and installation instructions.
AST API Tutorial The AST API tutorial (provided in all API languages) also uses plug-ins.

Specific API Language:

  Plug-In Guidelines Key API References
C++ Writing C++ Plug-Ins
(this page)
classes analysis, visitor, warningclass, project_metricclass, compunit_metricclass, sfile_metricclass, procedure_metricclass.
Python Writing Python Plug-Ins Visitor decorators, Metric decorators; classes analysis, warningclass, project_metricclass, compunit_metricclass, sfile_metricclass, procedure_metricclass.
C Writing C Plug-Ins CodeSonar Plug-In API: C Functions and Types for Visitors, Warnings, and Metrics