mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-2291 Support for unions through partial containers
This commit is contained in:
parent
d3efd60d54
commit
cb9c12894e
21 changed files with 678 additions and 182 deletions
|
@ -742,7 +742,7 @@ public class HighFunctionDBUtil {
|
|||
* pieces for building the dynamic LocalVariable. This method clears out any preexisting
|
||||
* union facet with the same dynamic hash and firstUseOffset.
|
||||
* @param function is the function affected by the union facet
|
||||
* @param dt is the parent data-type, either the union or a pointer to it
|
||||
* @param dt is the parent data-type; a union, a pointer to a union, or a partial union
|
||||
* @param fieldNum is the ordinal of the desired union field
|
||||
* @param addr is the first use address of the facet
|
||||
* @param hash is the dynamic hash
|
||||
|
@ -752,6 +752,9 @@ public class HighFunctionDBUtil {
|
|||
*/
|
||||
public static void writeUnionFacet(Function function, DataType dt, int fieldNum, Address addr,
|
||||
long hash, SourceType source) throws InvalidInputException, DuplicateNameException {
|
||||
if (dt instanceof PartialUnion) {
|
||||
dt = ((PartialUnion) dt).getParent();
|
||||
}
|
||||
int firstUseOffset = (int) addr.subtract(function.getEntryPoint());
|
||||
String symbolName = UnionFacetSymbol.buildSymbolName(fieldNum, addr);
|
||||
boolean nameCollision = false;
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import javax.help.UnsupportedOperationException;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
||||
/**
|
||||
* A data-type representing an unspecified piece of a parent Union data-type. This is used
|
||||
* internally by the decompiler to label Varnodes representing partial symbols, where the
|
||||
* part is known to be contained in a Union data-type. Within the isolated context of a Varnode,
|
||||
* its not possible to resolve to a specific field of the Union because the Varnode may be used
|
||||
* in multiple ways.
|
||||
*/
|
||||
public class PartialUnion extends AbstractDataType {
|
||||
private DataType unionDataType; // Either a Union or a Typedef of a Union
|
||||
private int offset; // Offset in bytes of partial within parent
|
||||
private int size; // Number of bytes in partial
|
||||
|
||||
PartialUnion(DataTypeManager dtm, DataType parent, int off, int sz) {
|
||||
super(CategoryPath.ROOT, "partialunion", dtm);
|
||||
unionDataType = parent;
|
||||
offset = off;
|
||||
size = sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Union data-type of which this is a part
|
||||
*/
|
||||
public DataType getParent() {
|
||||
return unionDataType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the offset, in bytes, of this part within its parent Union
|
||||
*/
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
// Internal to the PcodeDataTypeManager
|
||||
throw new UnsupportedOperationException("may not be cloned");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Partial Union (internal)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return null; // Should not be placed on memory
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return null; // Should not be placed on memory
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingsDefinition[] getSettingsDefinitions() {
|
||||
return unionDataType.getSettingsDefinitions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getDefaultSettings() {
|
||||
return unionDataType.getDefaultSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
// Internal to the PcodeDataTypeManager
|
||||
throw new UnsupportedOperationException("may not be copied");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
return unionDataType.getValueClass(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalent(DataType dt) {
|
||||
if (dt == null || !(dt instanceof PartialUnion)) {
|
||||
return false;
|
||||
}
|
||||
PartialUnion op = (PartialUnion) dt;
|
||||
if (offset != op.offset || size != op.size) {
|
||||
return false;
|
||||
}
|
||||
return unionDataType.isEquivalent(op.unionDataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlignment() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -251,6 +251,13 @@ public class PcodeDataTypeManager {
|
|||
decoder.closeElement(el);
|
||||
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
|
||||
}
|
||||
else if (meta.equals("partunion")) {
|
||||
int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
int offset = (int) decoder.readSignedInteger(ATTRIB_OFFSET);
|
||||
DataType dt = decodeDataType(decoder);
|
||||
decoder.closeElement(el);
|
||||
return new PartialUnion(progDataTypes, dt, offset, size);
|
||||
}
|
||||
else { // We typically reach here if the decompiler invents a new type
|
||||
// probably an unknown with a non-standard size
|
||||
int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue