This change implements a FDR trace dumping tool which allows us to
inspect the contents of an FDR mode trace in isolation. This is the
beginning of a larger refactoring of the FDR mode trace loading
implementation.
This change breaks up the FDR trace loading implementation into a number
of parts, allowing for better composition, testing, and extension.
The first part of this change is defining an abstract base type "Record"
which branches off into either a set of "MetadataRecord" types or
"FunctionRecord" instances. This allows us to then to isolate the logic
of reading data from a DataExtractor from interpreting the structure of
the log.
Doing this allows us to then more faithfully represent the data from a
trace as we see it from a log, independent of the semantic structure of
the trace.
The other part of this change involves defining a visitor abstraction,
which we use to process the log at a higher level of abstraction. It
allows us to process blocks of the trace more correctly, by grouping
individual records as blocks and arranging them by process+thread, and
interpreting the execution traces on a per-thread basis. To this end, we
implement a number of visitors which isolate the various higher-level
functions that operate on FDR traces. Some of these are:
- BlockIndexer: A visitor that generates an index grouping of blocks.
- RecordPrinter: A visitor that can print an individual Record instance.
- BlockPrinter: A visitor which defines a block-specific
pretty-printer.
- BlockValidator: A visitor that validates whether the log's structure is consistent with the expectations of the FDR mode log format.
We're starting the refactoring on the FDR mode implementation, then
performing a similar refactoring on the basic mode trace loading
implementation.
In this change we also take a chance to define a builder for each of the
record types, to allow us to generate valid and invalid sequences of
records in unit-testing. The builder interface is solely for testing
purposes.
newline?