diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc index dac7169ccd..178047f043 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc @@ -646,9 +646,9 @@ void FlowInfo::queryCall(FuncCallSpecs &fspecs) Funcdata *otherfunc = data.getScopeLocal()->getParent()->queryFunction( fspecs.getEntryAddress() ); if (otherfunc != (Funcdata *)0) { fspecs.setFuncdata(otherfunc); // Associate the symbol with the callsite - if (!fspecs.hasModel()) { // If the prototype was not overridden - fspecs.copyFlowEffects(otherfunc->getFuncProto()); // Take the symbols's prototype - // If the callsite is applying just the standard prototype from the symbol, + if (!fspecs.hasModel() || otherfunc->getFuncProto().isInline()) { // If the prototype was not overridden + fspecs.copyFlowEffects(otherfunc->getFuncProto()); // Take the flow affects of the symbol + // If the call site is applying just the standard prototype from the symbol, // this postpones the full copy of the prototype until ActionDefaultParams // Which lets "last second" changes come in, between when the function is first walked and // when it is finally decompiled diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerUtils.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerUtils.java index d95e60439f..3279a998fe 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerUtils.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerUtils.java @@ -755,6 +755,17 @@ public class DecompilerUtils { token = context.getTokenAtCursor(); } + return getDataType(token); + } + + /** + * Returns the data type for the given token + * + * @param token the token + * @return the data type or null + */ + public static DataType getDataType(ClangToken token) { + Varnode varnode = DecompilerUtils.getVarnodeRef(token); if (varnode != null) { HighVariable highVariable = varnode.getHigh(); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/hover/DataTypeDecompilerHover.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/hover/DataTypeDecompilerHover.java index cebf1d005e..263af2d369 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/hover/DataTypeDecompilerHover.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/hover/DataTypeDecompilerHover.java @@ -20,16 +20,19 @@ import javax.swing.JComponent; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; import ghidra.GhidraOptions; -import ghidra.app.decompiler.*; +import ghidra.app.decompiler.ClangFieldToken; +import ghidra.app.decompiler.ClangToken; import ghidra.app.decompiler.component.ClangTextField; +import ghidra.app.decompiler.component.DecompilerUtils; +import ghidra.app.plugin.core.datamgr.util.DataTypeUtils; import ghidra.app.plugin.core.hover.AbstractConfigurableHover; import ghidra.app.util.ToolTipUtils; import ghidra.framework.plugintool.PluginTool; -import ghidra.program.model.data.DataType; +import ghidra.program.model.data.*; import ghidra.program.model.listing.Program; -import ghidra.program.model.pcode.HighVariable; -import ghidra.program.model.pcode.Varnode; import ghidra.program.util.ProgramLocation; +import ghidra.util.HTMLUtilities; +import ghidra.util.NumericUtilities; public class DataTypeDecompilerHover extends AbstractConfigurableHover implements DecompilerHoverService { @@ -73,44 +76,77 @@ public class DataTypeDecompilerHover extends AbstractConfigurableHover } ClangToken token = ((ClangTextField) field).getToken(fieldLocation); - - DataType dt = getDataType(token); + DataType dt = DecompilerUtils.getDataType(token); if (dt == null) { - dt = getDataType(token.Parent()); + return null; } - if (dt != null) { - String toolTipText = ToolTipUtils.getToolTipText(dt); - return createTooltipComponent(toolTipText); + String toolTipText = null; + if (token instanceof ClangFieldToken) { + toolTipText = createFieldToolTipText((ClangFieldToken) token, dt); + } + else { + toolTipText = ToolTipUtils.getToolTipText(dt); } - return null; + return createTooltipComponent(toolTipText); } - private DataType getDataType(ClangNode node) { + private String createFieldToolTipText(ClangFieldToken token, DataType parentType) { + ClangFieldToken fieldToken = token; + int offset = fieldToken.getOffset(); + DataType fieldType = getFieldDataType(fieldToken); - if (node instanceof ClangVariableDecl) { - return ((ClangVariableDecl) node).getDataType(); + // + // Parent: BarBar + // Offset: 0x8 + // Field Name: fooField + // + + String BR = HTMLUtilities.BR; + StringBuilder newContent = new StringBuilder(); + newContent.append("
- * NOTE: When {@link DataTypeManagerDB} is instantiated for update an upgrade must be forced based upon the - * {@link CompositeDBAdapter#isFlexArrayMigrationRequired()} indicator. The upgrade logic - * (see {@link DataTypeManagerDB#migrateOldFlexArrayComponentsIfRequired(ghidra.util.task.TaskMonitor)}) - * istantiates all structures within the databases with an open transaaction allowing this method - * to perform the neccessary flex-array record migration. + * NOTE: When {@link DataTypeManagerDB} is instantiated for update an upgrade must be forced + * based upon the {@link CompositeDBAdapter#isFlexArrayMigrationRequired()} indicator. The + * upgrade logic(see + * {@link DataTypeManagerDB#migrateOldFlexArrayComponentsIfRequired(TaskMonitor)}) instantiates + * all structures within the databases with an open transaction allowing this method to perform + * the necessary flex-array record migration. *
- * NOTE: The offset of the migrated flex array component and structure length may change during upgrade - * when packing is enabled when the original packed structure length did not properly factor the flex-array - * alignment. Repack does not occur in the read-only case. + * NOTE: The offset of the migrated flex array component and structure length may change during + * upgrade when packing is enabled when the original packed structure length did not properly + * factor the flex-array alignment. Repack does not occur in the read-only case. * - * @param oldFlexArrayRecord record which corresponds to an olf flex-array component + * @param oldFlexArrayRecord record which corresponds to an old flex-array component * @throws IOException if a database error occurs */ private void migrateOldFlexArray(DBRecord oldFlexArrayRecord) throws IOException { long id = oldFlexArrayRecord.getLongValue(ComponentDBAdapter.COMPONENT_DT_ID_COL); DataType dt = dataMgr.getDataType(id); // could be BadDataType if built-in type is missing - // use zero-element array (need positive element length if dt is BadDataType) + // use zero-element array (need positive element length if type is BadDataType) dt = new ArrayDataType(dt, 0, 1, dataMgr); boolean repack = false; @@ -206,13 +197,14 @@ class StructureDB extends CompositeDB implements StructureInternal { DataTypeComponentDB dtc = null; try { if (dataType == DataType.DEFAULT) { - // assume non-packed structure - structre will grow by 1-byte below + // assume non-packed structure - structure will grow by 1-byte below dtc = new DataTypeComponentDB(dataMgr, this, numComponents, structLength); } else { int componentLength = getPreferredComponentLength(dataType, length); - DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key, - componentLength, numComponents, structLength, name, comment); + DBRecord rec = + componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key, + componentLength, numComponents, structLength, name, comment); dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); dataType.addParent(this); components.add(dtc); @@ -327,8 +319,9 @@ class StructureDB extends CompositeDB implements StructureInternal { length = getPreferredComponentLength(dataType, length); int offset = getComponent(ordinal).getOffset(); - DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key, length, - ordinal, offset, name, comment); + DBRecord rec = + componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key, length, + ordinal, offset, name, comment); DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); dataType.addParent(this); shiftOffsets(idx, 1, dtc.getLength()); @@ -553,8 +546,7 @@ class StructureDB extends CompositeDB implements StructureInternal { } /** - * Removes a defined component at the specified index without - * any alteration to other components. + * Removes a defined component at the specified index without any alteration to other components. * @param index defined component index * @return the defined component which was removed. * @throws IOException if an IO error occurs @@ -568,15 +560,15 @@ class StructureDB extends CompositeDB implements StructureInternal { /** * Removes a defined component at the specified index. - * If this corresponds to a zero-length or bit-field component it will - * be cleared without an offset shift to the remaining components. Removal of - * other component types will result in an offset and ordinal shift - * to the remaining components. In the case of a non-packed - * structure, the resulting shift will cause in a timestamp change - * for this structure. + *
+ * If this corresponds to a zero-length or bit-field component it will be cleared without an + * offset shift to the remaining components. Removal of other component types will result in + * an offset and ordinal shift to the remaining components. In the case of a non-packed + * structure, the resulting shift will cause in a timestamp change for this structure. + * * @param index defined component index - * @param disableOffsetShift if false, and component is not a bit-field, an offset shift - * and possible structure length change will be performed for non-packed structure. + * @param disableOffsetShift if false, and component is not a bit-field, an offset shift and + * possible structure length change will be performed for non-packed structure. */ private void doDeleteWithComponentShift(int index, boolean disableOffsetShift) { DataTypeComponentDB dtc = null; @@ -657,8 +649,9 @@ class StructureDB extends CompositeDB implements StructureInternal { } } + // update numComponents only components = newComponents; - updateComposite(numComponents + ordinalAdjustment, -1, -1, true); // update numComponents only + updateComposite(numComponents + ordinalAdjustment, -1, -1, true); if (isPackingEnabled()) { if (!repack(false, true)) { @@ -666,10 +659,11 @@ class StructureDB extends CompositeDB implements StructureInternal { } } else { - updateComposite(-1, structLength + offsetAdjustment, -1, true); // update length only + // update length only + updateComposite(-1, structLength + offsetAdjustment, -1, true); if (bitFieldRemoved) { repack(false, false); - } + } notifySizeChanged(false); } } @@ -781,10 +775,11 @@ class StructureDB extends CompositeDB implements StructureInternal { } /** - * Create copy of structure for target dtm (source archive information is discarded). + * Create copy of structure for target data type manager (source archive information is + * discarded). *
- * WARNING! copying non-packed structures which contain bitfields can produce invalid results when - * switching endianess due to the differences in packing order. + * WARNING! copying non-packed structures which contain bitfields can produce invalid results + * when switching endianness due to the differences in packing order. * * @param dtm target data type manager * @return cloned structure @@ -799,9 +794,10 @@ class StructureDB extends CompositeDB implements StructureInternal { } /** - * Create cloned structure for target dtm preserving source archive information. WARNING! - * cloning non-packed structures which contain bitfields can produce invalid results when - * switching endianess due to the differences in packing order. + * Create cloned structure for target data type manager preserving source archive information. + *
+ * WARNING! cloning non-packed structures which contain bitfields can produce invalid results
+ * when switching endianness due to the differences in packing order.
*
* @param dtm target data type manager
* @return cloned structure
@@ -884,7 +880,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
throw new IndexOutOfBoundsException(ordinal);
}
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
- OrdinalComparator.INSTANCE);
+ OrdinalComparator.INSTANCE);
if (idx >= 0) {
DataTypeComponentDB dtc = components.remove(idx);
dtc.getDataType().removeParent(this);
@@ -914,9 +910,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
/**
- * Backup from specified defined-component index to the first component which contains the specified offset.
- * @param index any defined component index which contains offset
- * @param offset offset within structure
+ * Backup from specified defined-component index to the first component which contains the
+ * specified offset.
+ *
+ * @param index any defined component index which contains offset.
+ * @param offset offset within structure.
* @return index of first defined component containing specific offset.
*/
private int backupToFirstComponentContainingOffset(int index, int offset) {
@@ -934,10 +932,12 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
/**
- * Identify defined-component index of the first non-zero-length component which contains the specified offset.
- * If only zero-length components exist, the last zero-length component which contains the offset will be returned.
- * @param index any defined component index which contains offset
- * @param offset offset within structure
+ * Identify defined-component index of the first non-zero-length component which contains the
+ * specified offset. If only zero-length components exist, the last zero-length component which
+ * contains the offset will be returned.
+ *
+ * @param index any defined component index which contains offset.
+ * @param offset offset within structure.
* @return index of first defined component containing specific offset.
*/
private int indexOfFirstNonZeroLenComponentContainingOffset(int index, int offset) {
@@ -954,9 +954,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
/**
- * Advance from specified defined-component index to the last component which contains the specified offset.
- * @param index any defined component index which contains offset
- * @param offset offset within structure
+ * Advance from specified defined-component index to the last component which contains the
+ * specified offset.
+ *
+ * @param index any defined component index which contains offset.
+ * @param offset offset within structure.
* @return index of last defined component containing specific offset.
*/
private int advanceToLastComponentContainingOffset(int index, int offset) {
@@ -993,7 +995,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
shiftOffsets(-index - 1, -1, -1); // updates timestamp
}
else {
- // delete all components containing offset working backward from last such component
+ // delete all components containing the offset working backward from the last such
+ // component
index = advanceToLastComponentContainingOffset(index, offset);
DataTypeComponentDB dtc = components.get(index);
while (dtc.containsOffset(offset)) {
@@ -1011,7 +1014,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
lock.release();
}
}
-
+
@Override
public void clearAtOffset(int offset) {
lock.acquire();
@@ -1109,7 +1112,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
lock.release();
}
}
-
+
@Override
public List