Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2025-03-19 13:16:18 -04:00
commit b3ed5feaea
4 changed files with 97 additions and 37 deletions

View file

@ -309,7 +309,7 @@ class StructureEditorModel extends CompEditorModel {
private int[] convertRowsToOrdinals(int[] rows) {
int[] ordinals = new int[rows.length];
DataTypeComponent[] definedComponents = ((Structure) viewComposite).getDefinedComponents();
DataTypeComponent[] definedComponents = viewComposite.getDefinedComponents();
for (int i = rows.length - 1; i >= 0; i--) {
ordinals[i] = definedComponents[rows[i]].getOrdinal();
}
@ -328,7 +328,7 @@ class StructureEditorModel extends CompEditorModel {
if (isShowingUndefinedBytes()) {
return rowIndex;
}
DataTypeComponent[] definedComponents = ((Structure) viewComposite).getDefinedComponents();
DataTypeComponent[] definedComponents = viewComposite.getDefinedComponents();
return definedComponents[rowIndex].getOrdinal();
}
@ -737,16 +737,16 @@ class StructureEditorModel extends CompEditorModel {
catch (InvalidDataTypeException e) {
return false;
}
if (isPackingEnabled() || isAtEnd(rowIndex)) {
return true;
}
int undefSize = getNumUndefinedBytesAfter(dtc);
if (undefSize < 0) {
return true;
}
int numAvailable = dtc.getLength() + undefSize;
return dataType.getLength() <= numAvailable;
}
@ -806,7 +806,7 @@ class StructureEditorModel extends CompEditorModel {
if (isPackingEnabled() || isAtEnd(currentIndex)) {
return Integer.MAX_VALUE;
}
// Can only replace with what fits unless at last component or empty last line.
DataTypeComponent comp = getComponent(currentIndex);
int numComponents = getNumComponents();
@ -820,9 +820,9 @@ class StructureEditorModel extends CompEditorModel {
// Otherwise, get size of component and number of Undefined bytes after it.
FieldRange currentRange = getSelectedRangeContaining(currentIndex);
boolean isOneComponent =
(currentRange == null) || (currentRange.getStart().getIndex().intValue() +
1 == currentRange.getEnd().getIndex().intValue());
(currentRange == null) || (currentRange.getStart().getIndex().intValue() +
1 == currentRange.getEnd().getIndex().intValue());
if (isOneComponent) {
return comp.getLength() + getNumUndefinedBytesAfter(comp);
}
@ -860,7 +860,7 @@ class StructureEditorModel extends CompEditorModel {
return viewDTM.withTransaction("Insert Component", () -> {
DataTypeComponent dtc;
if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) {
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name,
dtc = viewComposite.insert(rowIndex, dataType, length, name,
comment);
}
else {
@ -957,7 +957,8 @@ class StructureEditorModel extends CompEditorModel {
struct.growStructure(length - avail);
}
}
return ((Structure) viewComposite).replace(componentOrdinal, dataType, length, name, comment);
return ((Structure) viewComposite).replace(componentOrdinal, dataType, length,
name, comment);
});
}
return dtc;
@ -1266,8 +1267,9 @@ class StructureEditorModel extends CompEditorModel {
dialog.setStatusText("The name cannot match the external structure name.");
return false;
}
DataTypeManager originalDTM = getOriginalDataTypeManager();
DataType conflictingDt = originalDTM.getDataType(getOriginalCategoryPath(), name);
DataTypeManager originalDtm = getOriginalDataTypeManager();
DataType conflictingDt = originalDtm.getDataType(getOriginalCategoryPath(), name);
if (conflictingDt != null) {
dialog.setStatusText("A data type named \"" + name + "\" already exists.");
return false;

View file

@ -16,11 +16,14 @@
package ghidra.app.plugin.core.compositeeditor;
import java.math.BigInteger;
import java.util.*;
import javax.help.UnsupportedOperationException;
import javax.swing.table.TableColumn;
import docking.widgets.fieldpanel.support.FieldRange;
import docking.widgets.fieldpanel.support.FieldSelection;
import docking.widgets.table.GTableHeaderRenderer;
/**
* Data union editor model for maintaining information about the edits being
@ -53,6 +56,9 @@ class UnionEditorModel extends CompEditorModel {
private static final int DATATYPE = 2;
private static final int FIELDNAME = 3;
private static final int COMMENT = 4;
private static final int ORDINAL = 5;
private List<TableColumn> hiddenColumns;
UnionEditorModel(UnionEditorProvider provider, boolean showInHex) {
super(provider);
@ -62,6 +68,12 @@ class UnionEditorModel extends CompEditorModel {
adjustOffsets();
this.showHexNumbers = showInHex;
List<TableColumn> additionalColumns = new ArrayList<>();
TableColumn ordinalColumn = new TableColumn(ORDINAL, 75);
ordinalColumn.setHeaderRenderer(new GTableHeaderRenderer());
ordinalColumn.setHeaderValue("Ordinal");
additionalColumns.add(ordinalColumn);
hiddenColumns = Collections.unmodifiableList(additionalColumns);
}
@Override
@ -69,6 +81,11 @@ class UnionEditorModel extends CompEditorModel {
return "Union";
}
@Override
protected List<TableColumn> getHiddenColumns() {
return hiddenColumns;
}
@Override
public int getOffsetColumn() {
return -1;
@ -99,6 +116,29 @@ class UnionEditorModel extends CompEditorModel {
return COMMENT;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if ((viewComposite == null) || (rowIndex < 0) || (columnIndex < 0)) {
return "";
}
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc == null) {
if (columnIndex == getDataTypeColumn()) {
return null;
}
return "";
}
if (columnIndex == ORDINAL) {
int ordinal = dtc.getOrdinal();
return showHexNumbers ? getHexString(ordinal, true) : Integer.toString(ordinal);
}
return super.getValueAt(rowIndex, columnIndex);
}
/**
* returns whether or not a particular component row and field in this
* structure is editable.
@ -381,7 +421,7 @@ class UnionEditorModel extends CompEditorModel {
checkIsAllowableDataType(dataType);
try {
DataTypeComponent dtc = viewDTM.withTransaction("Add Component",
() -> ((Union) viewComposite).insert(rowIndex, dataType, length, name, comment));
() -> viewComposite.insert(rowIndex, dataType, length, name, comment));
if (rowIndex <= currentEditRow) {
currentEditRow++;
}
@ -418,8 +458,8 @@ class UnionEditorModel extends CompEditorModel {
try {
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));
DataTypeComponent dtc = viewDTM.withTransaction("Replace Component", () -> {
((Union) viewComposite).delete(rowIndex);
return ((Union) viewComposite).insert(rowIndex, dataType, length, name, comment);
viewComposite.delete(rowIndex);
return viewComposite.insert(rowIndex, dataType, length, name, comment);
});
if (isSelected) {
selection.addRange(rowIndex, rowIndex + 1);
@ -487,7 +527,7 @@ class UnionEditorModel extends CompEditorModel {
@Override
public void replaceOriginalComponents() {
((Union) getOriginalComposite()).replaceWith(viewComposite);
getOriginalComposite().replaceWith(viewComposite);
}
@Override

View file

@ -2285,7 +2285,13 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
monitor.checkCancelled();
if (specialTypeinfo.isInProgramMemory()) {
applyTypeinfoStructure(siClassTypeInfoStructure, specialTypeinfo.getAddress());
Data struct =
applyTypeinfoStructure(siClassTypeInfoStructure, specialTypeinfo.getAddress());
if (struct == null) {
Msg.error(this,
specialTypeinfo.getNamespace().getName() + ": cannot apply structure");
continue;
}
typeinfoToStructuretypeMap.put(specialTypeinfo.getAddress(),
SI_CLASS_TYPE_INFO_STRUCTURE);
}
@ -2725,13 +2731,19 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
}
private Data applyTypeinfoStructure(Structure typeInfoStructure, Address typeinfoAddress)
throws CancelledException, AddressOutOfBoundsException, Exception {
private Data applyTypeinfoStructure(Structure typeInfoStructure, Address typeinfoAddress) {
api.clearListing(typeinfoAddress, typeinfoAddress.add(typeInfoStructure.getLength() - 1));
Data newStructure = api.createData(typeinfoAddress, typeInfoStructure);
try {
api.clearListing(typeinfoAddress,
typeinfoAddress.add(typeInfoStructure.getLength() - 1));
Data newStructure = api.createData(typeinfoAddress, typeInfoStructure);
return newStructure;
}
catch (CodeUnitInsertionException | CancelledException e) {
Msg.warn(this, "Could not apply typeinfo struct at " + typeinfoAddress.toString());
return null;
}
return newStructure;
}
private Structure getOrCreateVmiTypeinfoStructure(Address typeinfoAddress,

View file

@ -2711,11 +2711,11 @@ public class RecoveredClassHelper {
}
// get only the functions from the ones that are not already processed structures
// return null if not an unprocessed table
// return null if not an unprocessed table or if invalid
List<Function> virtualFunctions = getFunctionsFromVftable(vftableAddress, vftableSymbol,
allowNullFunctionPtrs, allowDefaultRefsInMiddle);
// the vftable has already been processed - skip it
// the vftable has already been processed or invalid - skip it
if (virtualFunctions == null) {
continue;
}
@ -2769,20 +2769,19 @@ public class RecoveredClassHelper {
return recoveredClasses;
}
//TODO: rework above method to call this so it works with both that and other calls
protected void updateClassWithVftable(RecoveredClass recoveredClass, Symbol vftableSymbol,
boolean allowNullFunctionPtrs, boolean allowDefaultRefsInMiddle) throws Exception {
// get only the functions from the ones that are not already processed
// structures
// return null if not an unprocessed table
Address vftableAddress = vftableSymbol.getAddress();
Namespace vftableNamespace = vftableSymbol.getParentNamespace();
List<Function> virtualFunctions = getFunctionsFromVftable(vftableAddress, vftableSymbol,
allowNullFunctionPtrs, allowDefaultRefsInMiddle);
// the vftable has already been processed - skip it
// the vftable has already been processed or is invalid - skip it
if (virtualFunctions == null) {
return;
}
@ -2797,15 +2796,10 @@ public class RecoveredClassHelper {
recoveredClass.addVftableAddress(vftableAddress);
recoveredClass.addVftableVfunctionsMapping(vftableAddress, virtualFunctions);
// add it to the running list of RecoveredClass objects
// recoveredClasses.add(recoveredClass);
}
else {
recoveredClass.addVftableAddress(vftableAddress);
recoveredClass.addVftableVfunctionsMapping(vftableAddress, virtualFunctions);
// if (!recoveredClasses.contains(recoveredClass)) {
// recoveredClasses.add(recoveredClass);
// }
}
@ -2975,9 +2969,9 @@ public class RecoveredClassHelper {
// pointing to are in the class already to determine size of array
// create vtable
int numFunctionPointers =
Integer numFunctionPointers =
createVftable(vftableAddress, allowNullFunctionPtrs, allowDefaultRefsInMiddle);
if (numFunctionPointers == 0) {
if (numFunctionPointers == null || numFunctionPointers == 0) {
return null;
}
// make it an array
@ -3043,16 +3037,28 @@ public class RecoveredClassHelper {
* @param vftableAddress the vftable address
* @param allowNullFunctionPtrs if true allow vftables to have null pointers
* @param allowDefaultRefsInMiddle if true allow default references into the middle of the table
* @return the created array of pointers Data or null
* @return the number of functions in the table or null if none or in invalid block
* @throws CancelledException if cancelled
*/
public int createVftable(Address vftableAddress, boolean allowNullFunctionPtrs,
public Integer createVftable(Address vftableAddress, boolean allowNullFunctionPtrs,
boolean allowDefaultRefsInMiddle) throws CancelledException {
int numFunctionPointers = 0;
Address address = vftableAddress;
MemoryBlock currentBlock = program.getMemory().getBlock(vftableAddress);
if (currentBlock == null) {
Msg.warn(this, "Cannot create vftable at " + vftableAddress.toString() +
" because it is in an invalid memory block.");
return null;
}
if (currentBlock.isExternalBlock() || !currentBlock.isInitialized()) {
Msg.warn(this, "Cannot create vftable at " + vftableAddress.toString() +
" because it is in an external or an uninitialized block.");
return null;
}
boolean stillInCurrentTable = true;
while (address != null && currentBlock.contains(address) && stillInCurrentTable &&
extendedFlatAPI.isFunctionPointer(address, allowNullFunctionPtrs)) {