From 9fdd268d51000301301c54ba71e6b0adee383e7b Mon Sep 17 00:00:00 2001 From: datalocaltmp Date: Mon, 10 Jun 2024 11:55:29 -0400 Subject: [PATCH 1/8] Nicer theme for dark users and works for light users as well --- data/codecoverage.theme.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/codecoverage.theme.properties b/data/codecoverage.theme.properties index f0dac3f..c899ede 100644 --- a/data/codecoverage.theme.properties +++ b/data/codecoverage.theme.properties @@ -1,8 +1,8 @@ [Defaults] icon.cartographer.plugin.action.show.options = applications-system.png icon.cartographer.plugin.action.window = coverage.png -color.bg.plugin.overview.cartographer.decompiler = rgb(204, 204, 255) -color.bg.plugin.overview.cartographer.listing = rgb(204, 204, 255) +color.bg.plugin.overview.cartographer.decompiler = rgb(204, 109, 109) +color.bg.plugin.overview.cartographer.listing = rgb(204, 109, 109) color.bg.plugin.overview.cartographer.high = rgb(51, 153, 255) color.bg.plugin.overview.cartographer.low = rgb(255, 51, 51) color.bg.plugin.overview.cartographer.none = rgb(51, 51, 51) From cf607233479f27c83baec5b670144ef90cdf861c Mon Sep 17 00:00:00 2001 From: datalocaltmp Date: Mon, 10 Jun 2024 11:57:10 -0400 Subject: [PATCH 2/8] Change from DECOMPILER which no longer exists to DIAGNOSTIC --- src/main/java/cartographer/CartographerPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/cartographer/CartographerPlugin.java b/src/main/java/cartographer/CartographerPlugin.java index bbb7d35..78f16d9 100644 --- a/src/main/java/cartographer/CartographerPlugin.java +++ b/src/main/java/cartographer/CartographerPlugin.java @@ -67,7 +67,7 @@ @PluginInfo( status = PluginStatus.RELEASED, packageName = MiscellaneousPluginPackage.NAME, - category = PluginCategoryNames.DECOMPILER, + category = PluginCategoryNames.DIAGNOSTIC, shortDescription = "Code coverage parser", description = "Plugin for loading and processing code coverage data." ) From ef8e5f6fa871cb157a3d1e00b9dab27e041437ae Mon Sep 17 00:00:00 2001 From: datalocaltmp Date: Mon, 10 Jun 2024 12:03:09 -0400 Subject: [PATCH 3/8] Adding support for different Drcov module table formats across versions - based on /~https://github.com/gaasedelen/lighthouse/blob/562595be9bd99e8a5dfef6017d608467f5706630/plugins/lighthouse/reader/parsers/drcov.py#L413 --- src/main/java/cartographer/CoverageFile.java | 136 +++++++++++++++++-- 1 file changed, 125 insertions(+), 11 deletions(-) diff --git a/src/main/java/cartographer/CoverageFile.java b/src/main/java/cartographer/CoverageFile.java index 88b3715..c49f29f 100644 --- a/src/main/java/cartographer/CoverageFile.java +++ b/src/main/java/cartographer/CoverageFile.java @@ -30,6 +30,7 @@ import ghidra.program.model.address.AddressSpace; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; +import ghidra.util.Msg; /** * Represents a loaded coverage file with processed code coverage data. @@ -82,6 +83,7 @@ public String toString() { * @throws IOException If an I/O exception occurred */ public CoverageFile(String filename) throws IOException { + Msg.info("CoverageFile", "Loading filename: "+filename); // Filename without the pathname this.filename = filename.substring(filename.lastIndexOf('/') + 1); @@ -185,22 +187,33 @@ private void parseDrCovFile(RandomAccessFile reader) throws IOException { // Skip the column names reader.readLine(); - // Parse version 5 modules + // Parse modules for (int i = 0; i < numModules; i++) { // Read each module line = reader.readLine(); String[] moduleData = line.split(","); - // Get the parsed data - int moduleId = Integer.parseInt(moduleData[0].trim()); - int parentId = Integer.parseInt(moduleData[1].trim()); - int base = Integer.parseInt(moduleData[5].trim(), 16); - String name = moduleData[moduleData.length-1].trim(); - - // Create a new DrCov module - DrCovModule module = new DrCovModule(moduleId, parentId, base, name); - drcovModules.add(module); + // Add module data parsed by Drcov version + switch (version) { + case 1: + drcovModules.add(parseModuleV1(moduleData)); + break; + case 2: + drcovModules.add(parseModuleV2(moduleData)); + break; + case 3: + drcovModules.add(parseModuleV3(moduleData)); + break; + case 4: + drcovModules.add(parseModuleV4(moduleData)); + break; + case 5: + drcovModules.add(parseModuleV5(moduleData)); + break; + default: + break; + } } // Read the BB Table line @@ -239,6 +252,8 @@ private void parseDrCovFile(RandomAccessFile reader) throws IOException { short size = readShort(reader); int moduleId = readShort(reader) & 0xFFFF; + Msg.info("CoverageFile", "Adding block moduleId: " + moduleId + " offset: " + offset + " size: " + size); + // Make sure the module ID is valid if(moduleId < numModules){ // Add the block to the module @@ -267,7 +282,106 @@ private void parseDrCovFile(RandomAccessFile reader) throws IOException { // Populate the module list populateModules(drcovModules); } - + + // Parse DrcovModule entry v1, table: id, size, path + private DrCovModule parseModuleV1(String[] moduleData){ + + int moduleId = Integer.parseInt(moduleData[0].trim()); + + // parentId is 0 as it was not introduced until version 3 of Drcov module entry + int parentId = 0; + + // base is set as size as base was not introduced until version 2 of Drcov module entry + // likely that this Cartographer does not support V1 of Drcov format. + int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + + String name = moduleData[moduleData.length-1].trim(); + + return new DrCovModule( + moduleId, + parentId, + base, + name + ); + } + + // Parse DrcovModule entry v2, table: id, base, end, entry, checksum (windows), timestamp (windows), path + private DrCovModule parseModuleV2(String[] moduleData){ + + int moduleId = Integer.parseInt(moduleData[0].trim()); + + // parentId is 0 as it was not introduced until version 3 of Drcov module entry + int parentId = 0; + + int base = 0; + + String name = moduleData[moduleData.length-1].trim(); + + return new DrCovModule( + moduleId, + parentId, + base, + name + ); + } + + // Parse DrcovModule entry v3, table: id, containing_id, base, end, entry, checksum (windows), timestamp (windows), path + private DrCovModule parseModuleV3(String[] moduleData){ + + int moduleId = Integer.parseInt(moduleData[0].trim()); + + int parentId = Integer.parseInt(moduleData[1].trim()); + + int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + + String name = moduleData[moduleData.length-1].trim(); + + return new DrCovModule( + moduleId, + parentId, + base, + name + ); + } + + // Parse DrcovModule entry v4, table: id, containing_id, base, end, entry, offset, checksum (windows), timestamp (windows), path + private DrCovModule parseModuleV4(String[] moduleData){ + + int moduleId = Integer.parseInt(moduleData[0].trim()); + + int parentId = Integer.parseInt(moduleData[1].trim()); + + int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + + String name = moduleData[moduleData.length-1].trim(); + + return new DrCovModule( + moduleId, + parentId, + base, + name + ); + } + + // Parse DrcovModule entry v5, table: id, containing_id, base, end, entry, offset, preferred_base, checksum (windows), timestamp (windows), path + private DrCovModule parseModuleV5(String[] moduleData){ + + int moduleId = Integer.parseInt(moduleData[0].trim()); + + int parentId = Integer.parseInt(moduleData[1].trim()); + + int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + + String name = moduleData[moduleData.length-1].trim(); + + return new DrCovModule( + moduleId, + parentId, + base, + name + ); + } + /** * Populates the map of usable modules with those read from the DRCOV file. * From 9d6cabc3cdbf4a32d1b5e614f64699be5cb8aede Mon Sep 17 00:00:00 2001 From: datalocaltmp Date: Tue, 11 Jun 2024 11:29:11 -0400 Subject: [PATCH 4/8] DRCov v2 use base address --- src/main/java/cartographer/CoverageFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/cartographer/CoverageFile.java b/src/main/java/cartographer/CoverageFile.java index c49f29f..990c6c9 100644 --- a/src/main/java/cartographer/CoverageFile.java +++ b/src/main/java/cartographer/CoverageFile.java @@ -313,7 +313,7 @@ private DrCovModule parseModuleV2(String[] moduleData){ // parentId is 0 as it was not introduced until version 3 of Drcov module entry int parentId = 0; - int base = 0; + int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); From 835874a783fdf035c58745b8d73fd9c8090f73d6 Mon Sep 17 00:00:00 2001 From: datalocaltmp Date: Thu, 13 Jun 2024 16:34:16 -0400 Subject: [PATCH 5/8] Base can be larger than an int, adjust it to be a long --- src/main/java/cartographer/CoverageFile.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/cartographer/CoverageFile.java b/src/main/java/cartographer/CoverageFile.java index 990c6c9..67b1462 100644 --- a/src/main/java/cartographer/CoverageFile.java +++ b/src/main/java/cartographer/CoverageFile.java @@ -293,7 +293,7 @@ private DrCovModule parseModuleV1(String[] moduleData){ // base is set as size as base was not introduced until version 2 of Drcov module entry // likely that this Cartographer does not support V1 of Drcov format. - int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + long base = Long.parseUnsignedLong(moduleData[1].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); @@ -313,7 +313,7 @@ private DrCovModule parseModuleV2(String[] moduleData){ // parentId is 0 as it was not introduced until version 3 of Drcov module entry int parentId = 0; - int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + long base = Long.parseUnsignedLong(moduleData[1].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); @@ -332,7 +332,7 @@ private DrCovModule parseModuleV3(String[] moduleData){ int parentId = Integer.parseInt(moduleData[1].trim()); - int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); @@ -351,7 +351,7 @@ private DrCovModule parseModuleV4(String[] moduleData){ int parentId = Integer.parseInt(moduleData[1].trim()); - int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); @@ -370,7 +370,7 @@ private DrCovModule parseModuleV5(String[] moduleData){ int parentId = Integer.parseInt(moduleData[1].trim()); - int base = Integer.parseInt(moduleData[1].trim().replace("0x",""), 16); + long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); String name = moduleData[moduleData.length-1].trim(); @@ -403,7 +403,7 @@ private void populateModules(List modList) { // Add each block to the new module for (BasicBlock block : module.getBasicBlocks()) { - newMod.addBlock(block.offset + module.base, block.size, block.moduleId); + newMod.addBlock(block.offset, block.size, block.moduleId); } // Add the new module to the module list @@ -502,7 +502,7 @@ public class DrCovModule extends CodeCoverageModule { private int moduleId; private int parentId; - private int base; + private long base; private String name; /** @@ -513,7 +513,7 @@ public class DrCovModule extends CodeCoverageModule { * @param base Base memory address * @param name Name of the file */ - public DrCovModule(int moduleId, int parentId, int base, String name) { + public DrCovModule(int moduleId, int parentId, long base, String name) { this.moduleId = moduleId; this.parentId = parentId; this.base = base; From ec39a856ffff7cf8ef6f9516dcbcbc9d7ad6e248 Mon Sep 17 00:00:00 2001 From: b Date: Tue, 2 Jul 2024 15:52:42 +0200 Subject: [PATCH 6/8] Replaced Swing dialog with Ghidra's implementation This allows users to filter module names for easier selection. --- .../java/cartographer/CartographerPlugin.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/cartographer/CartographerPlugin.java b/src/main/java/cartographer/CartographerPlugin.java index 78f16d9..72b956d 100644 --- a/src/main/java/cartographer/CartographerPlugin.java +++ b/src/main/java/cartographer/CartographerPlugin.java @@ -20,6 +20,8 @@ import docking.action.DockingAction; import docking.action.MenuData; import docking.tool.ToolConstants; +import docking.widgets.DataToStringConverter; +import docking.widgets.ListSelectionDialog; import ghidra.app.decompiler.ClangToken; import ghidra.app.decompiler.DecompileResults; import ghidra.app.decompiler.DecompilerHighlightService; @@ -542,21 +544,15 @@ private boolean loadCoverageFile(CoverageFile file) { } // Ask the user which module to use - String response = (String)JOptionPane.showInputDialog( - null, - "Please select the code coverage module to use.", - "Select a Coverage Module", - JOptionPane.QUESTION_MESSAGE, - null, - modNames.toArray(), - modNames.get(0) - ); + ListSelectionDialog responseDialog = new ListSelectionDialog("Select a Coverage Module", "Module", modNames, DataToStringConverter.stringDataToStringConverter); + + responseDialog.show(tool.getActiveWindow()); + String response = responseDialog.getSelectedItem(); - // Bail if no option was chosen - if (response == null) { + if (responseDialog.wasCancelled()) { return false; } - + // Get the module data from the selected module option DrCovModule module = file.getModule(response); From 948be6d38d4805c0c6dde29c0a5425047e8345af Mon Sep 17 00:00:00 2001 From: b Date: Tue, 2 Jul 2024 17:16:58 +0200 Subject: [PATCH 7/8] Code formatting --- src/main/java/cartographer/CartographerPlugin.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/cartographer/CartographerPlugin.java b/src/main/java/cartographer/CartographerPlugin.java index 72b956d..79bdc2f 100644 --- a/src/main/java/cartographer/CartographerPlugin.java +++ b/src/main/java/cartographer/CartographerPlugin.java @@ -62,7 +62,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.swing.JOptionPane; import cartographer.CoverageFile.*; //@formatter:off @@ -544,7 +543,11 @@ private boolean loadCoverageFile(CoverageFile file) { } // Ask the user which module to use - ListSelectionDialog responseDialog = new ListSelectionDialog("Select a Coverage Module", "Module", modNames, DataToStringConverter.stringDataToStringConverter); + ListSelectionDialog responseDialog = new ListSelectionDialog( + "Select a Coverage Module", + "Module", + modNames, + DataToStringConverter.stringDataToStringConverter); responseDialog.show(tool.getActiveWindow()); String response = responseDialog.getSelectedItem(); @@ -552,7 +555,7 @@ private boolean loadCoverageFile(CoverageFile file) { if (responseDialog.wasCancelled()) { return false; } - + // Get the module data from the selected module option DrCovModule module = file.getModule(response); From 74794d83f18abc903c9dcd6147078f40de511db1 Mon Sep 17 00:00:00 2001 From: b Date: Wed, 11 Sep 2024 19:05:46 +0200 Subject: [PATCH 8/8] removed merge artifacts --- data/codecoverage.theme.properties | 4 +- src/main/java/cartographer/CoverageFile.java | 103 ------------------- 2 files changed, 2 insertions(+), 105 deletions(-) diff --git a/data/codecoverage.theme.properties b/data/codecoverage.theme.properties index c899ede..f0dac3f 100644 --- a/data/codecoverage.theme.properties +++ b/data/codecoverage.theme.properties @@ -1,8 +1,8 @@ [Defaults] icon.cartographer.plugin.action.show.options = applications-system.png icon.cartographer.plugin.action.window = coverage.png -color.bg.plugin.overview.cartographer.decompiler = rgb(204, 109, 109) -color.bg.plugin.overview.cartographer.listing = rgb(204, 109, 109) +color.bg.plugin.overview.cartographer.decompiler = rgb(204, 204, 255) +color.bg.plugin.overview.cartographer.listing = rgb(204, 204, 255) color.bg.plugin.overview.cartographer.high = rgb(51, 153, 255) color.bg.plugin.overview.cartographer.low = rgb(255, 51, 51) color.bg.plugin.overview.cartographer.none = rgb(51, 51, 51) diff --git a/src/main/java/cartographer/CoverageFile.java b/src/main/java/cartographer/CoverageFile.java index b424be6..6d7a08e 100644 --- a/src/main/java/cartographer/CoverageFile.java +++ b/src/main/java/cartographer/CoverageFile.java @@ -30,7 +30,6 @@ import ghidra.program.model.address.AddressSpace; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; -import ghidra.util.Msg; /** * Represents a loaded coverage file with processed code coverage data. @@ -84,7 +83,6 @@ public String toString() { * @throws IOException If an I/O exception occurred */ public CoverageFile(String filename) throws IOException { - Msg.info("CoverageFile", "Loading filename: "+filename); // Filename without the pathname this.filename = filename.substring(filename.lastIndexOf('/') + 1); @@ -239,8 +237,6 @@ private void parseDrCovFile(RandomAccessFile reader) throws IOException { short size = readShort(reader); int moduleId = readShort(reader) & 0xFFFF; - Msg.info("CoverageFile", "Adding block moduleId: " + moduleId + " offset: " + offset + " size: " + size); - // Make sure the module ID is valid if(moduleId < numModules){ // Add the block to the module @@ -270,105 +266,6 @@ private void parseDrCovFile(RandomAccessFile reader) throws IOException { populateModules(drcovModules); } - // Parse DrcovModule entry v1, table: id, size, path - private DrCovModule parseModuleV1(String[] moduleData){ - - int moduleId = Integer.parseInt(moduleData[0].trim()); - - // parentId is 0 as it was not introduced until version 3 of Drcov module entry - int parentId = 0; - - // base is set as size as base was not introduced until version 2 of Drcov module entry - // likely that this Cartographer does not support V1 of Drcov format. - long base = Long.parseUnsignedLong(moduleData[1].trim().replace("0x",""), 16); - - String name = moduleData[moduleData.length-1].trim(); - - return new DrCovModule( - moduleId, - parentId, - base, - name - ); - } - - // Parse DrcovModule entry v2, table: id, base, end, entry, checksum (windows), timestamp (windows), path - private DrCovModule parseModuleV2(String[] moduleData){ - - int moduleId = Integer.parseInt(moduleData[0].trim()); - - // parentId is 0 as it was not introduced until version 3 of Drcov module entry - int parentId = 0; - - long base = Long.parseUnsignedLong(moduleData[1].trim().replace("0x",""), 16); - - String name = moduleData[moduleData.length-1].trim(); - - return new DrCovModule( - moduleId, - parentId, - base, - name - ); - } - - // Parse DrcovModule entry v3, table: id, containing_id, base, end, entry, checksum (windows), timestamp (windows), path - private DrCovModule parseModuleV3(String[] moduleData){ - - int moduleId = Integer.parseInt(moduleData[0].trim()); - - int parentId = Integer.parseInt(moduleData[1].trim()); - - long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); - - String name = moduleData[moduleData.length-1].trim(); - - return new DrCovModule( - moduleId, - parentId, - base, - name - ); - } - - // Parse DrcovModule entry v4, table: id, containing_id, base, end, entry, offset, checksum (windows), timestamp (windows), path - private DrCovModule parseModuleV4(String[] moduleData){ - - int moduleId = Integer.parseInt(moduleData[0].trim()); - - int parentId = Integer.parseInt(moduleData[1].trim()); - - long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); - - String name = moduleData[moduleData.length-1].trim(); - - return new DrCovModule( - moduleId, - parentId, - base, - name - ); - } - - // Parse DrcovModule entry v5, table: id, containing_id, base, end, entry, offset, preferred_base, checksum (windows), timestamp (windows), path - private DrCovModule parseModuleV5(String[] moduleData){ - - int moduleId = Integer.parseInt(moduleData[0].trim()); - - int parentId = Integer.parseInt(moduleData[1].trim()); - - long base = Long.parseUnsignedLong(moduleData[2].trim().replace("0x",""), 16); - - String name = moduleData[moduleData.length-1].trim(); - - return new DrCovModule( - moduleId, - parentId, - base, - name - ); - } - /** * Parses a DRCOV module. *