mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch
'origin/GP-5957-dragonmacher-ascii-exporter-xref-fix' into patch (Closes #8468)
This commit is contained in:
commit
2537d2a329
2 changed files with 103 additions and 74 deletions
|
@ -25,7 +25,6 @@ import ghidra.program.model.symbol.*;
|
||||||
|
|
||||||
class ReferenceLineDispenser extends AbstractLineDispenser {
|
class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
|
|
||||||
private static final Address[] EMPTY_ADDR_ARR = new Address[0];
|
|
||||||
private final static String XREFS_DELIM = ",";
|
private final static String XREFS_DELIM = ",";
|
||||||
|
|
||||||
private int headerWidth;
|
private int headerWidth;
|
||||||
|
@ -52,10 +51,10 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
options.getAddrWidth() + options.getBytesWidth() + options.getLabelWidth();
|
options.getAddrWidth() + options.getBytesWidth() + options.getLabelWidth();
|
||||||
this.isHTML = options.isHTML();
|
this.isHTML = options.isHTML();
|
||||||
|
|
||||||
Address[] refs = (forwardRefs ? getForwardRefs(cu) : getXRefList(cu));
|
List<Reference> refs = (forwardRefs ? getForwardRefs(cu) : getXRefList(cu));
|
||||||
Address[] offcuts = (forwardRefs ? EMPTY_ADDR_ARR : getOffcutXRefList(cu));
|
List<Reference> offcuts = (forwardRefs ? List.of() : getOffcutXRefList(cu));
|
||||||
|
|
||||||
processRefs(cu.getMinAddress(), refs, offcuts);
|
processRefs(cu.getMinAddress(), forwardRefs, refs, offcuts);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReferenceLineDispenser(Variable var, Program program, ProgramTextOptions options) {
|
ReferenceLineDispenser(Variable var, Program program, ProgramTextOptions options) {
|
||||||
|
@ -74,20 +73,14 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
List<Reference> xrefs = new ArrayList<>();
|
List<Reference> xrefs = new ArrayList<>();
|
||||||
List<Reference> offcuts = new ArrayList<>();
|
List<Reference> offcuts = new ArrayList<>();
|
||||||
XReferenceUtils.getVariableRefs(var, xrefs, offcuts);
|
XReferenceUtils.getVariableRefs(var, xrefs, offcuts);
|
||||||
Address[] xrefAddr = extractFromAddr(xrefs);
|
|
||||||
Address[] offcutsAddr = extractFromAddr(offcuts);
|
|
||||||
|
|
||||||
processRefs(var.getFunction().getEntryPoint(),
|
Comparator<? super Reference> comparator = (r1, r2) -> {
|
||||||
xrefAddr, offcutsAddr);
|
return r1.getFromAddress().compareTo(r2.getFromAddress());
|
||||||
}
|
};
|
||||||
|
xrefs.sort(comparator);
|
||||||
|
offcuts.sort(comparator);
|
||||||
|
|
||||||
private Address[] extractFromAddr(List<Reference> refs) {
|
processRefs(var.getFunction().getEntryPoint(), false, xrefs, offcuts);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -110,7 +103,7 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private Address[] getForwardRefs(CodeUnit cu) {
|
private List<Reference> getForwardRefs(CodeUnit cu) {
|
||||||
boolean showRefs = false;
|
boolean showRefs = false;
|
||||||
|
|
||||||
Address cuAddr = cu.getMinAddress();
|
Address cuAddr = cu.getMinAddress();
|
||||||
|
@ -130,52 +123,48 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showRefs) {
|
if (!showRefs) {
|
||||||
return EMPTY_ADDR_ARR;
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference[] mRefs = cu.getReferencesFrom();
|
List<Reference> refs = Arrays.asList(cu.getReferencesFrom());
|
||||||
Address[] refs = new Address[mRefs.length];
|
refs.sort((r1, r2) -> {
|
||||||
for (int i = 0; i < mRefs.length; ++i) {
|
return r1.getToAddress().compareTo(r2.getToAddress());
|
||||||
refs[i] = mRefs[i].getToAddress();
|
});
|
||||||
}
|
|
||||||
Arrays.sort(refs);
|
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
private void processRefs(Address addr, boolean isForward, List<Reference> refs,
|
||||||
|
List<Reference> offcuts) {
|
||||||
private void processRefs(Address addr, Address[] refs, Address[] offcuts) {
|
|
||||||
if (width < 1) {
|
if (width < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (refs.length == 0 && offcuts.length == 0) {
|
if (refs.isEmpty() && offcuts.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
List<Reference> all = new ArrayList<>();
|
||||||
Address[] all = new Address[refs.length + offcuts.length];
|
all.addAll(refs);
|
||||||
System.arraycopy(refs, 0, all, 0, refs.length);
|
all.addAll(offcuts);
|
||||||
System.arraycopy(offcuts, 0, all, refs.length, offcuts.length);
|
|
||||||
|
|
||||||
if (displayRefHeader) {
|
if (displayRefHeader) {
|
||||||
if (refs.length > 0 || offcuts.length > 0) {
|
if (!refs.isEmpty() || !offcuts.isEmpty()) {
|
||||||
StringBuffer tmp = new StringBuffer();
|
|
||||||
tmp.append(header);
|
|
||||||
tmp.append("[");
|
|
||||||
tmp.append(refs.length);
|
|
||||||
tmp.append(",");
|
|
||||||
tmp.append(offcuts.length);
|
|
||||||
tmp.append("]: ");
|
|
||||||
|
|
||||||
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;
|
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,
|
//if we are not displaying the xref header,
|
||||||
//then we need to append the comment prefix
|
//then we need to append the comment prefix
|
||||||
if (i == 0 && !displayRefHeader) {
|
if (i == 0 && !displayRefHeader) {
|
||||||
|
@ -198,11 +187,17 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
}
|
}
|
||||||
|
|
||||||
//does memory contain this address? if so, then hyperlink it
|
//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) {
|
if (isHTML && isInMem) {
|
||||||
buf.append("<A HREF=\"#" + getUniqueAddressString(all[i]) + "\">");
|
buf.append("<A HREF=\"#" + getUniqueAddressString(address) + "\">");
|
||||||
}
|
}
|
||||||
buf.append(all[i].toString());
|
buf.append(address);
|
||||||
|
|
||||||
|
String refType = getRefTypeDisplayString(ref);
|
||||||
|
buf.append(refType);
|
||||||
|
|
||||||
if (isHTML && isInMem) {
|
if (isHTML && isInMem) {
|
||||||
buf.append("</A>");
|
buf.append("</A>");
|
||||||
}
|
}
|
||||||
|
@ -222,31 +217,62 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Address[] getXRefList(CodeUnit cu) {
|
// copied from XRefFieldFactory
|
||||||
Program prog = cu.getProgram();
|
private String getRefTypeDisplayString(Reference reference) {
|
||||||
if (prog == null) {
|
|
||||||
return new Address[0];
|
if (reference.getReferenceType().isRead() && reference.getReferenceType().isWrite()) {
|
||||||
}
|
return "(RW)";
|
||||||
List<Address> 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());
|
|
||||||
}
|
|
||||||
Address[] arr = new Address[xrefList.size()];
|
|
||||||
xrefList.toArray(arr);
|
|
||||||
Arrays.sort(arr);
|
|
||||||
return arr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Address[] getOffcutXRefList(CodeUnit cu) {
|
RefType refType = reference.getReferenceType();
|
||||||
|
if (reference instanceof ThunkReference) {
|
||||||
|
return "(T)";
|
||||||
|
}
|
||||||
|
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 "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Reference> getXRefList(CodeUnit cu) {
|
||||||
Program prog = cu.getProgram();
|
Program prog = cu.getProgram();
|
||||||
if (prog == null) {
|
if (prog == null) {
|
||||||
return new Address[0];
|
return List.of();
|
||||||
}
|
}
|
||||||
List<Address> offcutList = new ArrayList<>();
|
|
||||||
|
// default value taken from XRefFieldFactory
|
||||||
|
int maxXrefs = 20;
|
||||||
|
List<Reference> refs = XReferenceUtils.getXReferences(cu, maxXrefs + 1);
|
||||||
|
int maxOffcuts = Math.max(0, maxXrefs - refs.size());
|
||||||
|
List<Reference> offcuts = XReferenceUtils.getOffcutXReferences(cu, maxOffcuts);
|
||||||
|
refs.addAll(offcuts);
|
||||||
|
refs.sort((r1, r2) -> {
|
||||||
|
return r1.getFromAddress().compareTo(r2.getFromAddress());
|
||||||
|
});
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Reference> getOffcutXRefList(CodeUnit cu) {
|
||||||
|
Program prog = cu.getProgram();
|
||||||
|
if (prog == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Reference> offcutList = new ArrayList<>();
|
||||||
// Lookup the offcut xrefs...
|
// Lookup the offcut xrefs...
|
||||||
//
|
//
|
||||||
if (cu.getLength() > 1) {
|
if (cu.getLength() > 1) {
|
||||||
|
@ -259,13 +285,14 @@ class ReferenceLineDispenser extends AbstractLineDispenser {
|
||||||
ReferenceIterator refIter = refMgr.getReferencesTo(addr);
|
ReferenceIterator refIter = refMgr.getReferencesTo(addr);
|
||||||
while (refIter.hasNext()) {
|
while (refIter.hasNext()) {
|
||||||
Reference ref = refIter.next();
|
Reference ref = refIter.next();
|
||||||
offcutList.add(ref.getFromAddress());
|
offcutList.add(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Address[] arr = new Address[offcutList.size()];
|
|
||||||
offcutList.toArray(arr);
|
offcutList.sort((r1, r2) -> {
|
||||||
Arrays.sort(arr);
|
return r1.getFromAddress().compareTo(r2.getFromAddress());
|
||||||
return arr;
|
});
|
||||||
|
return offcutList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.program.model.address.Address;
|
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.model.symbol.Reference;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.XRefHeaderFieldLocation;
|
import ghidra.program.util.XRefHeaderFieldLocation;
|
||||||
|
@ -132,8 +133,9 @@ public class XRefHeaderFieldFactory extends XRefFieldFactory {
|
||||||
if (cu == null) {
|
if (cu == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Program prog = cu.getProgram();
|
|
||||||
int xrefCount = prog.getReferenceManager().getReferenceCountTo(cu.getMinAddress());
|
List<Reference> xrefs = XReferenceUtils.getXReferences(cu, maxXRefs);
|
||||||
|
int xrefCount = xrefs.size();
|
||||||
List<Reference> offcuts = XReferenceUtils.getOffcutXReferences(cu, maxXRefs);
|
List<Reference> offcuts = XReferenceUtils.getOffcutXReferences(cu, maxXRefs);
|
||||||
int offcutCount = offcuts.size();
|
int offcutCount = offcuts.size();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue