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()
.
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.
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.