mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-18 16:40:08 +00:00
Merge remote-tracking branch
'origin/GP-3949_ghidra1_FixOldSTVariableStorageScript--SQUASHED' into patch (Closes #5640)
This commit is contained in:
commit
3371301ac6
@ -0,0 +1,174 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// This fixup script is intended to be run against x86 programs created prior
|
||||||
|
// to Ghidra 10.0.3 to update old ST0..ST7 floating point register
|
||||||
|
// locations assigned to function parameters and local variables. The
|
||||||
|
// address assignment for these registers was changed with Ghidra 10.0.3
|
||||||
|
// x86 slaspec change (GP-1228).
|
||||||
|
//
|
||||||
|
// This script can be run multiple times without harm
|
||||||
|
//@category Functions
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
import ghidra.program.model.symbol.*;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
|
public class FixOldSTVariableStorageScript extends GhidraScript {
|
||||||
|
|
||||||
|
private static final int ST_SIZE = 10;
|
||||||
|
|
||||||
|
// See Ghidra/Processors/x86/data/languages/ia.sinc
|
||||||
|
private static final long OLD_ST_BASE_OFFSET = 0x1000;
|
||||||
|
private static final long OLD_ST_OFFSET_SPACING = ST_SIZE; // each offset 10-bytes from the previous
|
||||||
|
|
||||||
|
// Must query new ST0 address since it may change again
|
||||||
|
private static final long NEW_ST_OFFSET_SPACING = 16; // each offset 16-bytes from the previous
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run() throws Exception {
|
||||||
|
|
||||||
|
if (currentProgram == null || !"x86".equals(currentProgram.getLanguage().getProcessor().toString())) {
|
||||||
|
popup("Script supports x86 programs only");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spot check new ST0 placement
|
||||||
|
Register st0 = currentProgram.getRegister("ST0");
|
||||||
|
Register st1 = currentProgram.getRegister("ST1");
|
||||||
|
if (st0 == null || st1 == null) {
|
||||||
|
popup("Unsupported x86 language");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long st0Offset = st0.getAddress().getOffset();
|
||||||
|
long st1Offset = st1.getAddress().getOffset();
|
||||||
|
if (st0Offset == OLD_ST_BASE_OFFSET || (st1Offset - st0Offset) != NEW_ST_OFFSET_SPACING) {
|
||||||
|
popup("Unsupported x86 ST register placement");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
STRegisterFixup stRegisterFixup = new STRegisterFixup(st0Offset);
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||||
|
for (Symbol s : symbolTable.getDefinedSymbols()) {
|
||||||
|
SymbolType type = s.getSymbolType();
|
||||||
|
if (type == SymbolType.PARAMETER || type == SymbolType.LOCAL_VAR) {
|
||||||
|
if (stRegisterFixup.fixupVariableStorage((Variable) s.getObject())) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == SymbolType.FUNCTION) {
|
||||||
|
Function function = (Function) s.getObject();
|
||||||
|
if (stRegisterFixup.fixupVariableStorage(function.getReturn())) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 0) {
|
||||||
|
popup("Fixed " + count + " ST register uses");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
popup("No old ST register uses were found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class STRegisterFixup {
|
||||||
|
|
||||||
|
private Set<Varnode> oldSTVarnodes; // ST0..ST7
|
||||||
|
private long newStBaseOffset;
|
||||||
|
|
||||||
|
STRegisterFixup(long newStBaseOffset) {
|
||||||
|
this.newStBaseOffset = newStBaseOffset;
|
||||||
|
|
||||||
|
AddressSpace registerSpace = currentProgram.getAddressFactory().getRegisterSpace();
|
||||||
|
|
||||||
|
long oldSTBaseOffset = OLD_ST_BASE_OFFSET;
|
||||||
|
oldSTVarnodes = Set.of(
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset),
|
||||||
|
ST_SIZE), // Old ST0 at 0x1000, now at 0x1106
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + OLD_ST_OFFSET_SPACING),
|
||||||
|
ST_SIZE), // Old ST1 at 0x100a, now at 0x1116
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (2 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE), // Old ST2 at 0x1014, now at 0x1126
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (3 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE), // Old ST3 at 0x101e, now at 0x1136
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (4 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE), // Old ST4 at 0x1028, now at 0x1146
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (5 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE), // Old ST5 at 0x1032, now at 0x1156
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (6 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE), // Old ST6 at 0x103c, now at 0x1166
|
||||||
|
new Varnode(registerSpace.getAddress(oldSTBaseOffset + (7 * OLD_ST_OFFSET_SPACING)),
|
||||||
|
ST_SIZE) // Old ST7 at 0x1046*, now at 0x1176 // Old ST7 at 0x1046, now at 0x1176
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean fixupVariableStorage(Variable var) {
|
||||||
|
VariableStorage varStore = var.getVariableStorage();
|
||||||
|
Varnode[] varnodes = varStore.getVarnodes();
|
||||||
|
if (fixupStorageVarnodes(varnodes)) {
|
||||||
|
try {
|
||||||
|
var.setDataType(var.getDataType(),
|
||||||
|
new VariableStorage(currentProgram, varnodes), false, var.getSource());
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
throw new AssertionError("Unexpected error for ST register varnode assignment",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean fixupStorageVarnodes(Varnode[] varnodes) {
|
||||||
|
boolean hasFixup = false;
|
||||||
|
for (int i = 0; i < varnodes.length; i++) {
|
||||||
|
Varnode v = getReplacement(varnodes[i]);
|
||||||
|
if (v != null) {
|
||||||
|
hasFixup = true;
|
||||||
|
varnodes[i] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasFixup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Varnode getReplacement(Varnode v) {
|
||||||
|
if (!oldSTVarnodes.contains(v)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Address regAddr = v.getAddress();
|
||||||
|
long stOffset = regAddr.getOffset() - OLD_ST_BASE_OFFSET;
|
||||||
|
long stIndex = stOffset / OLD_ST_OFFSET_SPACING;
|
||||||
|
|
||||||
|
// Form updated ST varnode
|
||||||
|
stOffset = newStBaseOffset + (stIndex * NEW_ST_OFFSET_SPACING);
|
||||||
|
return new Varnode(regAddr.getNewAddress(stOffset), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user