Wednesday, February 25, 2015

Attack of the Codes or the Phantom Menace

A few weeks back I talked about Undead Code, how it can erode your code base and how it can be brought back to life by an errant change. Recall that some of the criterion were that it be logically dead, awaiting someone to trigger the right parameters and bring it back to life. Today, after a short conversation with a co-worker on some "This has to be dead code", I went back to figure out why my normal tool-chain wasn't flagging it.

In doing so I found yet another, interesting, nearly invisible bit of undead code. This code is compiled, linked into objects, formed into libraries, and yet somehow, when pitched from the binary, doesn't leave a trace. No indication that it was ever part of your compilation unit. Normally I would be able to find discarded symbols with discard tracking options. But in this case, if there were 0 symbols used in the object, then it appears there is nothing to discard.

At first I thought that maybe there would be some other symbol I could use or some other indication, like an unused object record. In my search I couldn't find one. Then I figured, well, all of the used files actually show up. In fact, if you use a tool from the DIA SDK called Dia2Dump, then it has a files option (-f) that will print the contribution to each object and library from the files that were compiled. You can go a step further and even get line number contribution which can lead to some really interesting tools such as when the compiler can evaluate a constant expression in your code (that you think it somehow no constant) and it throws out either the if or else block as a result.

Lets stop at the files though. You use "dia2dump -f" to get the file contributions, then you compare this against the files in your source tree. What you end up with is a restricted set of files that are in your tree, but for whatever reason are not part of the final binary. You'll probably be amazed at what you find. I found the following types of items in case you are interested.

  1. Large helper templates for type-safe casting.
  2. Drawing helpers, used by another file that was no flagged as either a) Linker Dead Code or b) by my new file technique. In this case I believe they would have been identified once I started pruning the leaves.
  3. A sub-parser we no longer use.
  4. Some base class functions and helpers that weren't used or should have been marked pure.
Some of the code in order to compile, requires libraries and other dependencies not needed by any of the code that contributes to the binary. This allowed for further reductions in the build files which is always welcome.

As the title suggests I'm going to call this kind of code "The Phantom Menace" and I'll be improving my tool chains to report it accurately while at the same time figuring out why some additional dependent files weren't found.

--- Errata
If you want to remove build dependencies then setting your LINKER_FLAGS to /VERBOSE:UNUSEDLIBS can point out a lot of useless junk that you are loading and scanning. Using this with the Dia2Dump sample, you'll find uuid.lib is not needed apparently.

I can publish more of these tools, but internally I use a different tool than Dia2Dump. Also, the Dia2Dump that I just built out of the VS 2014 preview I have on hand, crashes on some inputs.

No comments:

Post a Comment