From 6ea07f858c4ba804eb4348f30fe6fc193d378b68 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 9 Feb 2021 18:22:11 -0500 Subject: [PATCH] GP-421 - Allow plate comments in structures; allow pre-comments at the top of structures Closes #2091 --- .../core/commentwindow/CommentTableModel.java | 41 +++++++++++-------- .../util/viewer/field/PlateFieldFactory.java | 39 ++++++++++++++---- .../viewer/field/PreCommentFieldFactory.java | 14 +++---- 3 files changed, 62 insertions(+), 32 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentTableModel.java index 3e1eea7221..9259cf36ca 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentTableModel.java @@ -84,23 +84,30 @@ class CommentTableModel extends AddressBasedTableModel { listing.getCommentAddressIterator(getProgram().getMemory(), true); while (commentIterator.hasNext()) { Address commentAddr = commentIterator.next(); - CodeUnit cu = listing.getCodeUnitAt(commentAddr); - if (cu != null) { - if (cu.getComment(CodeUnit.PRE_COMMENT) != null) { - accumulator.add(new CommentRowObject(commentAddr, CodeUnit.PRE_COMMENT)); - } - if (cu.getComment(CodeUnit.POST_COMMENT) != null) { - accumulator.add(new CommentRowObject(commentAddr, CodeUnit.POST_COMMENT)); - } - if (cu.getComment(CodeUnit.EOL_COMMENT) != null) { - accumulator.add(new CommentRowObject(commentAddr, CodeUnit.EOL_COMMENT)); - } - if (cu.getComment(CodeUnit.PLATE_COMMENT) != null) { - accumulator.add(new CommentRowObject(commentAddr, CodeUnit.PLATE_COMMENT)); - } - if (cu.getComment(CodeUnit.REPEATABLE_COMMENT) != null) { - accumulator.add(new CommentRowObject(commentAddr, CodeUnit.REPEATABLE_COMMENT)); - } + CodeUnit cu = listing.getCodeUnitContaining(commentAddr); + if (!(cu instanceof Data)) { + // avoid too many comments in the table by not showing offcut instruction comments + cu = listing.getCodeUnitAt(commentAddr); + } + + if (cu == null) { + continue; + } + + if (cu.getComment(CodeUnit.PRE_COMMENT) != null) { + accumulator.add(new CommentRowObject(commentAddr, CodeUnit.PRE_COMMENT)); + } + if (cu.getComment(CodeUnit.POST_COMMENT) != null) { + accumulator.add(new CommentRowObject(commentAddr, CodeUnit.POST_COMMENT)); + } + if (cu.getComment(CodeUnit.EOL_COMMENT) != null) { + accumulator.add(new CommentRowObject(commentAddr, CodeUnit.EOL_COMMENT)); + } + if (cu.getComment(CodeUnit.PLATE_COMMENT) != null) { + accumulator.add(new CommentRowObject(commentAddr, CodeUnit.PLATE_COMMENT)); + } + if (cu.getComment(CodeUnit.REPEATABLE_COMMENT) != null) { + accumulator.add(new CommentRowObject(commentAddr, CodeUnit.REPEATABLE_COMMENT)); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java index 2a4e0c0711..f28bd38910 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java @@ -27,6 +27,7 @@ import ghidra.app.util.HighlightProvider; import ghidra.app.util.viewer.format.FieldFormatModel; import ghidra.app.util.viewer.listingpanel.ListingModel; import ghidra.app.util.viewer.options.OptionsGui; +import ghidra.app.util.viewer.proxy.DataProxy; import ghidra.app.util.viewer.proxy.ProxyObj; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; @@ -126,10 +127,10 @@ public class PlateFieldFactory extends FieldFactory { nLinesBeforeLabels = fieldOptions.getInt(LINES_BEFORE_LABELS_OPTION, 1); nLinesBeforePlates = fieldOptions.getInt(LINES_BEFORE_PLATES_OPTION, 0); - showExternalFunctionPointerPlates = fieldOptions.getBoolean( - ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true); - showNonExternalFunctionPointerPlates = fieldOptions.getBoolean( - ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false); + showExternalFunctionPointerPlates = fieldOptions + .getBoolean(ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true); + showNonExternalFunctionPointerPlates = fieldOptions + .getBoolean(ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false); } @@ -160,11 +161,32 @@ public class PlateFieldFactory extends FieldFactory { FieldElement[] fields = new FieldElement[elementList.size()]; elementList.toArray(fields); + if (isNestedDataAtSameAddressAsParent(proxy)) { + // This is data at the same address as the parent, which happens with the first + // element in a structure. We do not want to the plate comment here, but only at the + // parent topmost address. + return null; + } + PlateFieldTextField textField = new PlateFieldTextField(fields, this, proxy, startX, width, commentText, isClipped); return new PlateListingTextField(proxy, textField); } + private boolean isNestedDataAtSameAddressAsParent(ProxyObj proxy) { + if (proxy instanceof DataProxy) { + DataProxy dp = (DataProxy) proxy; + Data data = dp.getObject(); + int[] cpath = data.getComponentPath(); + if (cpath.length > 0) { + if (cpath[cpath.length - 1] == 0) { + return true; + } + } + } + return false; + } + private String getCommentText(CodeUnit cu) { String[] comments = cu.getCommentAsArray(CodeUnit.PLATE_COMMENT); if (comments == null) { @@ -199,8 +221,8 @@ public class PlateFieldFactory extends FieldFactory { AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics()); for (int i = 0; i < comments.length; i++) { - elementList.add( - CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i)); + elementList + .add(CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i)); } if (isWordWrap) { @@ -499,7 +521,10 @@ public class PlateFieldFactory extends FieldFactory { if (!CodeUnit.class.isAssignableFrom(proxyObjectClass)) { return false; } - return (category == FieldFormatModel.PLATE); + + // some users like the look of plate comments and would like them in many places + return (category == FieldFormatModel.PLATE || category == FieldFormatModel.OPEN_DATA || + category == FieldFormatModel.INSTRUCTION_OR_DATA); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java index d07a2a1a1c..7f333da0b7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java @@ -120,16 +120,14 @@ public class PreCommentFieldFactory extends FieldFactory { private String[] getDefinedPreComments(CodeUnit cu) { - // If this code unit is the outside of a data - // container, then do not display any comments. - // If this was allowed, then the comment would appear - // on the outside data container and on the 1st - // internal member - // + // Do not show comments for nested components that share the same address as their parent if (cu instanceof Data) { Data data = (Data) cu; - if (data.getNumComponents() > 0) { - return null; + int[] cpath = data.getComponentPath(); + if (cpath.length > 0) { + if (cpath[cpath.length - 1] == 0) { + return null; + } } }