|
27 | 27 | import ghidra.app.util.viewer.format.FieldFormatModel;
|
28 | 28 | import ghidra.app.util.viewer.listingpanel.ListingModel;
|
29 | 29 | import ghidra.app.util.viewer.options.OptionsGui;
|
| 30 | +import ghidra.app.util.viewer.proxy.DataProxy; |
30 | 31 | import ghidra.app.util.viewer.proxy.ProxyObj;
|
31 | 32 | import ghidra.framework.options.Options;
|
32 | 33 | import ghidra.framework.options.ToolOptions;
|
@@ -126,10 +127,10 @@ private PlateFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
126 | 127 | nLinesBeforeLabels = fieldOptions.getInt(LINES_BEFORE_LABELS_OPTION, 1);
|
127 | 128 | nLinesBeforePlates = fieldOptions.getInt(LINES_BEFORE_PLATES_OPTION, 0);
|
128 | 129 |
|
129 |
| - showExternalFunctionPointerPlates = fieldOptions.getBoolean( |
130 |
| - ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true); |
131 |
| - showNonExternalFunctionPointerPlates = fieldOptions.getBoolean( |
132 |
| - ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false); |
| 130 | + showExternalFunctionPointerPlates = fieldOptions |
| 131 | + .getBoolean(ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true); |
| 132 | + showNonExternalFunctionPointerPlates = fieldOptions |
| 133 | + .getBoolean(ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false); |
133 | 134 |
|
134 | 135 | }
|
135 | 136 |
|
@@ -160,11 +161,32 @@ public ListingField getField(ProxyObj<?> proxy, int varWidth) {
|
160 | 161 | FieldElement[] fields = new FieldElement[elementList.size()];
|
161 | 162 | elementList.toArray(fields);
|
162 | 163 |
|
| 164 | + if (isNestedDataAtSameAddressAsParent(proxy)) { |
| 165 | + // This is data at the same address as the parent, which happens with the first |
| 166 | + // element in a structure. We do not want to the plate comment here, but only at the |
| 167 | + // parent topmost address. |
| 168 | + return null; |
| 169 | + } |
| 170 | + |
163 | 171 | PlateFieldTextField textField =
|
164 | 172 | new PlateFieldTextField(fields, this, proxy, startX, width, commentText, isClipped);
|
165 | 173 | return new PlateListingTextField(proxy, textField);
|
166 | 174 | }
|
167 | 175 |
|
| 176 | + private boolean isNestedDataAtSameAddressAsParent(ProxyObj<?> proxy) { |
| 177 | + if (proxy instanceof DataProxy) { |
| 178 | + DataProxy dp = (DataProxy) proxy; |
| 179 | + Data data = dp.getObject(); |
| 180 | + int[] cpath = data.getComponentPath(); |
| 181 | + if (cpath.length > 0) { |
| 182 | + if (cpath[cpath.length - 1] == 0) { |
| 183 | + return true; |
| 184 | + } |
| 185 | + } |
| 186 | + } |
| 187 | + return false; |
| 188 | + } |
| 189 | + |
168 | 190 | private String getCommentText(CodeUnit cu) {
|
169 | 191 | String[] comments = cu.getCommentAsArray(CodeUnit.PLATE_COMMENT);
|
170 | 192 | if (comments == null) {
|
@@ -199,8 +221,8 @@ private boolean generateFormattedPlateComment(List<FieldElement> elementList, Co
|
199 | 221 | AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
|
200 | 222 |
|
201 | 223 | for (int i = 0; i < comments.length; i++) {
|
202 |
| - elementList.add( |
203 |
| - CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i)); |
| 224 | + elementList |
| 225 | + .add(CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i)); |
204 | 226 | }
|
205 | 227 |
|
206 | 228 | if (isWordWrap) {
|
@@ -499,7 +521,10 @@ public boolean acceptsType(int category, Class<?> proxyObjectClass) {
|
499 | 521 | if (!CodeUnit.class.isAssignableFrom(proxyObjectClass)) {
|
500 | 522 | return false;
|
501 | 523 | }
|
502 |
| - return (category == FieldFormatModel.PLATE); |
| 524 | + |
| 525 | + // some users like the look of plate comments and would like them in many places |
| 526 | + return (category == FieldFormatModel.PLATE || category == FieldFormatModel.OPEN_DATA || |
| 527 | + category == FieldFormatModel.INSTRUCTION_OR_DATA); |
503 | 528 | }
|
504 | 529 |
|
505 | 530 | @Override
|
|
0 commit comments