Build coreutils as a single binary
Then, run a command like this: This release was bootstrapped with the following tools: Previously they set the context of an existing directory to that of its last copied descendent. A W E [These dd bugs were present in "the beginning". Duplicates are elided for virtual file systems like tmpfs. Details for the correct device are output for points mounted multiple times. Placeholder values are output for inaccessible file systems, rather than than error messages or values for the wrong file system.
On some systems, entries would have been incorrectly elided due to them being considered "dummy" mounts. Previously it would issue a warning and exit with a failure status.
Previously nothing was output in this case. Previously, in the default output format, it would print the default group ID in the password database, which may be neither real nor effective. Previously it would display an error, requiring --no-dereference to avoid the issue.
Now works as expected. Previously in locales where character 0xA0 is a blank, numfmt would mishandle it. With the symlinks option, you can't make a second symlink to any program because that will change the name of the called program, which is used by coreutils to determine the desired program. To make the environment variable persistent, add the export to your shell profile e. As before, we will build in a separate directory so we can easily access both the native executables and the LLVM versions.
Notice that we made two changes. Second, when running make, we set the CC variable to point to wllvm. You may notice that instead of LLVM bitcode files, we obtained executable files. WLLVM stores the location of the generated bitcode files in a dedicated section of the object file. When object files are linked together, the locations are concatenated to save the locations of all constituent files.
After the build completes, one can use the WLLVM utility extract-bc to read the contents of the dedicated section and link all of the bitcode into a single whole-program bitcode file.
To obtain the LLVM bitcode version of all Coreutils, we can invoke extract-bc on all executable files:. For example, here is how to run the same cat command we did before, using KLEE. We got a lot more output this time! In order for KLEE to work effectively, it needs to have definitions for all the external functions the program may call.
Similarly, a native application would be running on top of an operating system that provides lower level facilities like write , which the C library uses in its implementation. As before, KLEE needs definitions for these functions in order to fully understand the program. As before, cat prints out its version information note that this time all the text is written out , but we now have a number of additional information output by KLEE. In this case, most of these warnings are innocuous, but for completeness here is what they mean:.
In general, KLEE will only emit a given warning once. The warnings are also logged to warnings. For example, lets look at running KLEE on the echo application. This function alters the normal command line processing of the application, in particular to support construction of symbolic arguments. For example, passing —help yields:. The results here are slightly more interesting, KLEE has explored 25 paths through the program. The output from all the paths is intermingled, but you can see that in addition to echoing various random characters, some blocks of text also were output.
You may be wondering why the percentages are so low — how much more code can echo have! The main reason is that these numbers are computed using all the instructions or branches in the bitcode files; that includes a lot of library code which may not even be executable.
We can help with that problem and others by passing the --optimize option to KLEE. When working with non-trivial applications, it is almost always a good idea to use this flag. Here are the results from running again with --optimze enabled:. This time the instruction coverage went up by about six percent, and you can see that KLEE also ran faster and executed less instructions. We can verify this — and look for uncovered code inside echo — by using KCachegrind to visualize the results of a KLEE run.
KCachegrind is an excellent profiling visualization tool, originally written for use with the callgrind plugin for valgrind.
KLEE by default writes out a run. In this example, the run. Assuming you have KCachegrind installed, just run:. After KCachegrind opens, you should see a window that looks something like the one below. KCachegrind is a complex application in itself, and interested users should see the KCachegrind website for more information and documentation.
KLEE includes quite a few statistics about execution. If you select that statistic and resort the list of functions, you should see something like this:. Notice that most of the uncovered instructions are in library code as we would expect.
If you look a bit more, you can see that this is a flag set to true when -e is passed. One subtle thing to understand if you are trying to actually make sense of the KCachegrind numbers is that they include events accumulated across all states. For example, consider the following code:.