From 210520cd07db6626f6c0cfa3e5931b967e748050 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:31:31 -0400 Subject: [PATCH] GP-5957 - Fixed missing reference type in the ASCII and HTML exporters --- .../util/exporter/ReferenceLineDispenser.java | 165 ++++++++++-------- .../viewer/field/XRefHeaderFieldFactory.java | 12 +- 2 files changed, 103 insertions(+), 74 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ReferenceLineDispenser.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ReferenceLineDispenser.java index 63585b8193..710741bc0f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ReferenceLineDispenser.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ReferenceLineDispenser.java @@ -25,7 +25,6 @@ import ghidra.program.model.symbol.*; class ReferenceLineDispenser extends AbstractLineDispenser { - private static final Address[] EMPTY_ADDR_ARR = new Address[0]; private final static String XREFS_DELIM = ","; private int headerWidth; @@ -52,10 +51,10 @@ class ReferenceLineDispenser extends AbstractLineDispenser { options.getAddrWidth() + options.getBytesWidth() + options.getLabelWidth(); this.isHTML = options.isHTML(); - Address[] refs = (forwardRefs ? getForwardRefs(cu) : getXRefList(cu)); - Address[] offcuts = (forwardRefs ? EMPTY_ADDR_ARR : getOffcutXRefList(cu)); + List refs = (forwardRefs ? getForwardRefs(cu) : getXRefList(cu)); + List offcuts = (forwardRefs ? List.of() : getOffcutXRefList(cu)); - processRefs(cu.getMinAddress(), refs, offcuts); + processRefs(cu.getMinAddress(), forwardRefs, refs, offcuts); } ReferenceLineDispenser(Variable var, Program program, ProgramTextOptions options) { @@ -74,20 +73,14 @@ class ReferenceLineDispenser extends AbstractLineDispenser { List xrefs = new ArrayList<>(); List offcuts = new ArrayList<>(); XReferenceUtils.getVariableRefs(var, xrefs, offcuts); - Address[] xrefAddr = extractFromAddr(xrefs); - Address[] offcutsAddr = extractFromAddr(offcuts); - processRefs(var.getFunction().getEntryPoint(), - xrefAddr, offcutsAddr); - } + Comparator comparator = (r1, r2) -> { + return r1.getFromAddress().compareTo(r2.getFromAddress()); + }; + xrefs.sort(comparator); + offcuts.sort(comparator); - private Address[] extractFromAddr(List refs) { - Address[] addrs = new Address[refs.size()]; - for (int i = 0; i < addrs.length; i++) { - addrs[i] = refs.get(i).getFromAddress(); - } - Arrays.sort(addrs); - return addrs; + processRefs(var.getFunction().getEntryPoint(), false, xrefs, offcuts); } @Override @@ -110,7 +103,7 @@ class ReferenceLineDispenser extends AbstractLineDispenser { //////////////////////////////////////////////////////////////////// - private Address[] getForwardRefs(CodeUnit cu) { + private List getForwardRefs(CodeUnit cu) { boolean showRefs = false; Address cuAddr = cu.getMinAddress(); @@ -130,52 +123,48 @@ class ReferenceLineDispenser extends AbstractLineDispenser { } if (!showRefs) { - return EMPTY_ADDR_ARR; + return List.of(); } - Reference[] mRefs = cu.getReferencesFrom(); - Address[] refs = new Address[mRefs.length]; - for (int i = 0; i < mRefs.length; ++i) { - refs[i] = mRefs[i].getToAddress(); - } - Arrays.sort(refs); + List refs = Arrays.asList(cu.getReferencesFrom()); + refs.sort((r1, r2) -> { + return r1.getToAddress().compareTo(r2.getToAddress()); + }); return refs; } - //////////////////////////////////////////////////////////////////// - - private void processRefs(Address addr, Address[] refs, Address[] offcuts) { + private void processRefs(Address addr, boolean isForward, List refs, + List offcuts) { if (width < 1) { return; } - if (refs.length == 0 && offcuts.length == 0) { + if (refs.isEmpty() && offcuts.isEmpty()) { return; } StringBuffer buf = new StringBuffer(); - - Address[] all = new Address[refs.length + offcuts.length]; - System.arraycopy(refs, 0, all, 0, refs.length); - System.arraycopy(offcuts, 0, all, refs.length, offcuts.length); + List all = new ArrayList<>(); + all.addAll(refs); + all.addAll(offcuts); if (displayRefHeader) { - if (refs.length > 0 || offcuts.length > 0) { - StringBuffer tmp = new StringBuffer(); - tmp.append(header); - tmp.append("["); - tmp.append(refs.length); - tmp.append(","); - tmp.append(offcuts.length); - tmp.append("]: "); + if (!refs.isEmpty() || !offcuts.isEmpty()) { - buf.append(clip(tmp.toString(), headerWidth)); + String text; + if (!offcuts.isEmpty()) { + text = "%s[%d,%d]: ".formatted(header, refs.size(), offcuts.size()); + } + else { + text = "%s[%d]: ".formatted(header, refs.size()); + } + buf.append(clip(text, headerWidth)); } } - int refsPerLine = width / (all[0].toString().length() + XREFS_DELIM.length()); + int refsPerLine = width / (all.get(0).toString().length() + XREFS_DELIM.length()); int refsInCurrLine = 0; - for (int i = 0; i < all.length; ++i) { + for (int i = 0; i < all.size(); ++i) { //if we are not displaying the xref header, //then we need to append the comment prefix if (i == 0 && !displayRefHeader) { @@ -198,11 +187,17 @@ class ReferenceLineDispenser extends AbstractLineDispenser { } //does memory contain this address? if so, then hyperlink it - boolean isInMem = memory.contains(all[i]); + Reference ref = all.get(i); + Address address = isForward ? ref.getToAddress() : ref.getFromAddress(); + boolean isInMem = memory.contains(address); if (isHTML && isInMem) { - buf.append(""); + buf.append(""); } - buf.append(all[i].toString()); + buf.append(address); + + String refType = getRefTypeDisplayString(ref); + buf.append(refType); + if (isHTML && isInMem) { buf.append(""); } @@ -222,31 +217,62 @@ class ReferenceLineDispenser extends AbstractLineDispenser { } } - public static Address[] getXRefList(CodeUnit cu) { - Program prog = cu.getProgram(); - if (prog == null) { - return new Address[0]; + // copied from XRefFieldFactory + private String getRefTypeDisplayString(Reference reference) { + + if (reference.getReferenceType().isRead() && reference.getReferenceType().isWrite()) { + return "(RW)"; } - List
xrefList = new ArrayList<>(); - //lookup the direct xrefs to the current code unit - // - ReferenceIterator iter = prog.getReferenceManager().getReferencesTo(cu.getMinAddress()); - while (iter.hasNext()) { - Reference ref = iter.next(); - xrefList.add(ref.getFromAddress()); + + RefType refType = reference.getReferenceType(); + if (reference instanceof ThunkReference) { + return "(T)"; } - Address[] arr = new Address[xrefList.size()]; - xrefList.toArray(arr); - Arrays.sort(arr); - return arr; + if (refType instanceof DataRefType) { + if (refType.isRead() || refType.isIndirect()) { + return "(R)"; + } + else if (refType.isWrite()) { + return "(W)"; + } + else if (refType.isData()) { + return "(*)"; + } + } + if (refType.isCall()) { + return "(c)"; + } + else if (refType.isJump()) { + return "(j)"; + } + return ""; } - private static Address[] getOffcutXRefList(CodeUnit cu) { + public static List getXRefList(CodeUnit cu) { Program prog = cu.getProgram(); if (prog == null) { - return new Address[0]; + return List.of(); } - List
offcutList = new ArrayList<>(); + + // default value taken from XRefFieldFactory + int maxXrefs = 20; + List refs = XReferenceUtils.getXReferences(cu, maxXrefs + 1); + int maxOffcuts = Math.max(0, maxXrefs - refs.size()); + List offcuts = XReferenceUtils.getOffcutXReferences(cu, maxOffcuts); + refs.addAll(offcuts); + refs.sort((r1, r2) -> { + return r1.getFromAddress().compareTo(r2.getFromAddress()); + }); + return refs; + } + + private static List getOffcutXRefList(CodeUnit cu) { + Program prog = cu.getProgram(); + if (prog == null) { + return List.of(); + } + + List offcutList = new ArrayList<>(); // Lookup the offcut xrefs... // if (cu.getLength() > 1) { @@ -259,13 +285,14 @@ class ReferenceLineDispenser extends AbstractLineDispenser { ReferenceIterator refIter = refMgr.getReferencesTo(addr); while (refIter.hasNext()) { Reference ref = refIter.next(); - offcutList.add(ref.getFromAddress()); + offcutList.add(ref); } } } - Address[] arr = new Address[offcutList.size()]; - offcutList.toArray(arr); - Arrays.sort(arr); - return arr; + + offcutList.sort((r1, r2) -> { + return r1.getFromAddress().compareTo(r2.getFromAddress()); + }); + return offcutList; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefHeaderFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefHeaderFieldFactory.java index cde7804861..2eb430c9bb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefHeaderFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefHeaderFieldFactory.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,7 +28,8 @@ import ghidra.app.util.viewer.proxy.ProxyObj; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; import ghidra.program.model.address.Address; -import ghidra.program.model.listing.*; +import ghidra.program.model.listing.CodeUnit; +import ghidra.program.model.listing.Data; import ghidra.program.model.symbol.Reference; import ghidra.program.util.ProgramLocation; import ghidra.program.util.XRefHeaderFieldLocation; @@ -132,8 +133,9 @@ public class XRefHeaderFieldFactory extends XRefFieldFactory { if (cu == null) { return null; } - Program prog = cu.getProgram(); - int xrefCount = prog.getReferenceManager().getReferenceCountTo(cu.getMinAddress()); + + List xrefs = XReferenceUtils.getXReferences(cu, maxXRefs); + int xrefCount = xrefs.size(); List offcuts = XReferenceUtils.getOffcutXReferences(cu, maxXRefs); int offcutCount = offcuts.size();