A monolithic semiconductor substrate

Chip Design Journal

Subscribe to Chip Design Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Chip Design Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

Chip Design Authors: Jnan Dash, Jason Bloomberg, Trevor Bradley, David Strom

Related Topics: Chip Design

Chip Design: Article

Inside View: Parasoft Insure++ 7.0 for Linux

Both 32- and 64-bit x86 support

My first encounter with Parasoft Insure++ and Parasoft Corporation was in the mid-'90s when I was working for a small company developing parsers and translators for languages used in semiconductor chip design. Like developers on almost any development project, we ran into a "runaway" memory situation -typically called "leaks," ours was more like a "flood" - that took quite a bit of time, effort, and frank conversations to debug by hand. After that incident, we started looking at memory debugging tools, Insure++ (in version 2.1 back then) being one of them. In the course of a diligent evaluation, we were favorably impressed with the robustness and accuracy of Insure++ memory analysis.

There was, however, a problem: the tool was slower than our application would tolerate for meaningful debugging. A Parasoft salesman was completely unfazed when I told him, "We won't buy unless you fix this." He told me that I would have to work with Adam. "OK, give me his e-mail," I said. So, Adam and I started talking back and forth, and after a number of versions of Insure++ shared libraries that were turned around in remarkably short time, the instrumented code was running several times faster - enough to satisfy our requirements.

It turned out that Parasoft had to redesign some of their memory-tracking algorithms to deal with the peculiarities in our code. We happily bought the tool.

Imagine my surprise when after a while I learned that the engineer I worked with was actually Parasoft's CEO and founder Adam Kolawa. I found this level of customer support quite remarkable especially for a customer that was such a small company. We kept in touch, and quite a few years and two companies later, I found myself working for Parasoft.

The current Insure++ is an established tool for runtime memory analysis and debugging. Now up to version 7.0, it runs on Red Hat, Mandrake, Debian, SuSE, MontaVista, and Yellow Dog Linux. New to 7.0 is Linux support on AMD's 64-bit Opteron and Intel's EM64T processors - Insure++ is now the only tool in its class to support both 32- and 64-bit programs on these up and coming processors.

Besides Linux, Insure++ supports a wide range of platforms and compilers, including Windows, Solaris, even AIX. Although its core features haven't significantly changed since I first used it almost a decade ago, its infrastructure support and analysis capabilities have. A key change in Insure++ 7.0 is a third-party parser, also used in a number of commercial compilers. This upgrade improves the robustness of code analysis and results in radical runtime improvements in the code instrumentation phase, relative to the previous release (10x and more, depending on the specifics of code being analyzed).

With the vast expressive power of C and C++ comes a rather daunting array of ways that programmers can shoot themselves in the foot by improperly using language features or semantics. Insure++ finds a variety of programming and memory-access errors such as:

  • Memory corruption due to reading or writing beyond the valid areas of global objects or those allocated on heap or stack
  • Incorrect pointer operations
  • Memory leaks and allocate/free errors
  • String manipulation errors
  • Buffer overflows
  • Stack overflows.
Insure++ checks the validity of each memory reference - including references to static (global) and stack as well as dynamically allocated memory - when the reference is used. When Insure++ finds a problem, it reports the name of related variables, the line of source code containing the error, a description of the error, and a stack trace. Its reports can be analyzed with a graphical front-end called Insra, or dumped into text files (see Figure 1).

There are three ways to use Insure++ for memory debugging on Linux. The most detailed analysis is achieved with full source code instrumentation. This requires that application sources be compiled and linked with Insure++, which generates its own instrumented files that are passed to the actual compiler. Compiling source code with Insure++ is generally as simple as prepending insure before your compiler. For example, gcc -c foo.c becomes insure gcc -c foo.c and g++ -c bar.cc becomes insure g++ -c bar.cc. As a matter of convenience, Insure++ offers options to select a given subset of files for instrumentation (the same effect can be accomplished with simple changes to your makefiles), or even specific functions in a file, with the intent to reduce the runtime overhead.

The second option is linking with Insure++, which gives the user a trade-off between the extent of error reporting and the actual time to build and run an instrumented application. Third, Insure++ includes a Chaperon mode, exclusive to Linux/x86. Chaperon checks all the data memory references a process makes, whether in the developer's compiled code, language support routines, shared libraries, or operating system kernel calls. Chaperon detects and reports reads of uninitialized memory, reads or writes that are not in the bounds of allocated blocks, and allocation errors such as memory leaks.

As memory leaks go, Insure++ doesn't just report them all as unreferenced memory. Thanks to its patented source code instrumentation technology, it has a fine enough handle on what's going on with the code to report three different types of leaks:

  • Leaks on freeing memory, when a freed object contained pointers to other memory that's no longer referenced.
  • Leaks on return, when a function allocates memory for its return value, but the value is never used.
  • Leaks of memory going out of scope, when functions allocate memory in their body but never free it.
What's more, Insure++ reports memory leaks in real-time (when it's running). This real-time reporting makes the debug and fix process much easier than when you get a blob of leaked memory at the end of a program run and are left to untangle the causes of these leaks. In my experience, Insure++ indisputably has the most comprehensive memory-checking capabilities.

The TCA (Total Coverage Analysis) code coverage module comes bundled with Insure++. Code coverage information is collected by Insure++ over multiple runs and is displayed color-coded in a graphical file browser (see Figure 2).

You might not need code coverage analysis when you're chasing a single memory bug, but you'll benefit from the integrated coverage analysis tool if you eliminate memory and other bugs during development, in the spirit of error prevention.

Any description of memory debugging would be incomplete without discussing the actual debugger. Programs compiled with Insure++ can be run under gdb. Insure++ provides a number of public API functions that stop execution at the exact point of error. Creating a breakpoint in a function _Insure_trap_error achieves that, while inserting a call to _Insure_checking_enable into your code lets you turn debugging on and off.

Insure++ provides plenty of options to deal with libraries. Most applications aren't self-contained and typically depend on third-party or system libraries. Insure++ will analyze memory errors in those libraries as long as the libraries are instrumented with Insure++. Version 7.0 of Insure comes with pre-defined interfaces to various existing libraries; these interfaces let the tool intercept important API calls and report associated errors. Alternatively, if your product is a library but you have no access to the application using the library, you can still provide an Insure++-instrumented version of the library, and be able to get all Insure++-specific runtime diagnostics.

In conclusion, I'd like to point out a certain misconception about the role of memory debuggers in the development process. A memory debugger typically comes into play when the program already has a confirmed bug. Only then do developers spend time running source through the memory analysis tool. Instead, memory analysis should be a part of regular white-box and regression analysis, so that memory bugs don't turn up in the released versions, causing developer angst when they surface at customer sites. Insure++ is a robust and versatile memory debugger that will support both applications.

For more information on Insure++, other Parasoft products, and Parasoft's Automated Error Prevention methodology, please visit www.parasoft.com or call 1-888-305-0041.

More Stories By Sergei Sokolov

Sergei Sokolov is a senior member of the Professional Services team at Parasoft, a provider of software development tools that help control and optimize the software development process.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.