3. Generating profile data

Things don't get any simpler at this point, unfortunately. At this point we've collected and classified the sample files into the set of inverted profiles, as described in the previous section. Now we need to process each inverted profile and make something of the data. The entry point for this is populate_for_image().

3.1. Processing the binary image

The first thing we do with an inverted profile is attempt to open the binary image (remember each inverted profile set is only for one binary image, but may have many sample files to process). The op_bfd class provides an abstracted interface to this; internally it uses libbfd. The main purpose of this class is to process the symbols for the binary image; this is also where symbol filtering happens. This is actually quite tricky, but should be clear from the source.

3.2. Processing the sample files

The class profile_container is a hold-all that contains all the processed results. It is a container of profile_t objects. The add_sample_files() method uses libdb to open the given sample file and add the key/value types to the profile_t. Once this has been done, profile_container::add() is passed the profile_t plus the op_bfd for processing.

profile_container::add() walks through the symbols collected in the op_bfd. op_bfd::get_symbol_range() gives us the start and end of the symbol as an offset from the start of the binary image, then we interrogate the profile_t for the relevant samples for that offset range. We create a symbol_entry object for this symbol and fill it in. If needed, here we also collect debug information from the op_bfd, and possibly record the detailed sample information (as used by opreport -d and opannotate). Finally the symbol_entry is added to a private container of profile_container - this symbol_container holds all such processed symbols.