diff --git a/plugin/lighthouse/parsers/drcov.py b/plugin/lighthouse/parsers/drcov.py index 726fc3a7..d724f30c 100644 --- a/plugin/lighthouse/parsers/drcov.py +++ b/plugin/lighthouse/parsers/drcov.py @@ -156,7 +156,7 @@ def _parse_module_table_header(self, f): eg: 'Module Table: 11' Format used in DynamoRIO v7.0.0-RC1 (and hopefully above) - eg: 'Module Table: version 2, count 11' + eg: 'Module Table: version X, count 11' """ @@ -191,6 +191,8 @@ def _parse_module_table_header(self, f): data_name, version = version_data.split(" ") #assert data_name == "version" self.module_table_version = int(version) + if not self.module_table_version in [2, 3, 4]: + raise ValueError("Unsupported (new?) drcov log format...") # parse module count in table from 'count Y' data_name, count = count_data.split(" ") @@ -203,15 +205,27 @@ def _parse_module_table_columns(self, f): ------------------------------------------------------------------- - Format used in DynamoRIO v6.1.1 through 6.2.0 + DynamoRIO v6.1.1, table version 1: eg: (Not present) - Format used in DynamoRIO v7.0.0-RC1 (and hopefully above) + DynamoRIO v7.0.0-RC1, table version 2: Windows: 'Columns: id, base, end, entry, checksum, timestamp, path' Mac/Linux: 'Columns: id, base, end, entry, path' + DynamoRIO v7.0.17594B, table version 3: + Windows: + 'Columns: id, containing_id, start, end, entry, checksum, timestamp, path' + Mac/Linux: + 'Columns: id, containing_id, start, end, entry, path' + + DynamoRIO v7.0.17640, table version 4: + Windows: + 'Columns: id, containing_id, start, end, entry, offset, checksum, timestamp, path' + Mac/Linux: + 'Columns: id, containing_id, start, end, entry, offset, path' + """ # NOTE/COMPAT: there is no 'Columns' line for the v1 table... @@ -308,10 +322,20 @@ def __init__(self, module_data, version): self.timestamp = 0 self.path = "" self.filename = "" + self.containing_id = 0 # parse the module self._parse_module(module_data, version) + @property + def start(self): + """ + Compatability alias for the module base. + + DrCov table version 2 --> 3 changed this paramter name base --> start. + """ + return self.base + def _parse_module(self, module_line, version): """ Parse a module table entry. @@ -323,6 +347,10 @@ def _parse_module(self, module_line, version): self._parse_module_v1(data) elif version == 2: self._parse_module_v2(data) + elif version == 3: + self._parse_module_v3(data) + elif version == 4: + self._parse_module_v4(data) else: raise ValueError("Unknown module format (v%u)" % version) @@ -350,6 +378,39 @@ def _parse_module_v2(self, data): self.size = self.end-self.base self.filename = os.path.basename(self.path) + def _parse_module_v3(self, data): + """ + Parse a module table v3 entry. + """ + self.id = int(data[0]) + self.containing_id = int(data[1]) + self.base = int(data[2], 16) + self.end = int(data[3], 16) + self.entry = int(data[4], 16) + if len(data) == 7: # Windows Only + self.checksum = int(data[5], 16) + self.timestamp = int(data[6], 16) + self.path = str(data[-1]) + self.size = self.end-self.base + self.filename = os.path.basename(self.path) + + def _parse_module_v4(self, data): + """ + Parse a module table v4 entry. + """ + self.id = int(data[0]) + self.containing_id = int(data[1]) + self.base = int(data[2], 16) + self.end = int(data[3], 16) + self.entry = int(data[4], 16) + self.offset = int(data[5], 16) + if len(data) == 7: # Windows Only + self.checksum = int(data[6], 16) + self.timestamp = int(data[7], 16) + self.path = str(data[-1]) + self.size = self.end-self.base + self.filename = os.path.basename(self.path) + #------------------------------------------------------------------------------ # drcov basic block parser #------------------------------------------------------------------------------ diff --git a/plugin/lighthouse_plugin.py b/plugin/lighthouse_plugin.py index 9f7972c5..18f921b3 100644 --- a/plugin/lighthouse_plugin.py +++ b/plugin/lighthouse_plugin.py @@ -20,7 +20,7 @@ # IDA Plugin #------------------------------------------------------------------------------ -PLUGIN_VERSION = "0.7.1" +PLUGIN_VERSION = "0.7.2" AUTHORS = "Markus Gaasedelen" DATE = "2017" @@ -684,7 +684,8 @@ def _load_coverage_files(self, filenames): # catch all for parse errors / bad input / malformed files except Exception as e: lmsg("Failed to load coverage %s" % filename) - logger.exception("Error details:") + lmsg(" - Error: %s" % str(e)) + logger.exception(" - Traceback:") continue # save the loaded coverage data to the output list