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