mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
b3ed5feaea
4 changed files with 97 additions and 37 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue