mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 07:30:16 +00:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
a37f663a23
@ -65,8 +65,8 @@ public class CoffSectionHeader implements StructConverter {
|
||||
s_scnptr = reader.readNextInt();
|
||||
s_relptr = reader.readNextInt();
|
||||
s_lnnoptr = reader.readNextInt();
|
||||
s_nreloc = reader.readNextShort() & 0xffff;
|
||||
s_nlnno = reader.readNextShort() & 0xffff;
|
||||
s_nreloc = reader.readNextUnsignedShort();
|
||||
s_nlnno = reader.readNextUnsignedShort();
|
||||
s_flags = reader.readNextInt();
|
||||
s_reserved = 0;
|
||||
s_page = 0;
|
||||
@ -306,14 +306,6 @@ public class CoffSectionHeader implements StructConverter {
|
||||
struct.add(WORD, "s_nreloc", null);
|
||||
struct.add(WORD, "s_nlnno", null);
|
||||
struct.add(DWORD, "s_flags", null);
|
||||
if (_header.getMagic() == CoffMachineType.TICOFF1MAGIC) {
|
||||
struct.add(BYTE, "s_reserved", null);
|
||||
struct.add(BYTE, "s_page", null);
|
||||
}
|
||||
else if (_header.getMagic() == CoffMachineType.TICOFF2MAGIC) {
|
||||
struct.add(WORD, "s_reserved", null);
|
||||
struct.add(WORD, "s_page", null);
|
||||
}
|
||||
return struct;
|
||||
}
|
||||
|
||||
@ -400,6 +392,10 @@ public class CoffSectionHeader implements StructConverter {
|
||||
public static Address getAddress(Language language, long offset, CoffSectionHeader section) {
|
||||
boolean isData = section == null || section.isData();
|
||||
AddressSpace space = isData ? language.getDefaultDataSpace() : language.getDefaultSpace();
|
||||
if (offset > space.getMaxAddress().getAddressableWordOffset()) {
|
||||
// offset too big to fit, try the opposite space, so at least the blocks will load
|
||||
space = !isData ? language.getDefaultDataSpace() : language.getDefaultSpace();
|
||||
}
|
||||
return space.getAddress(offset * getOffsetUnitSize(language, section));
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@ package ghidra.app.util.bin.format.coff;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
/**
|
||||
* A 0x28 byte COFF section header
|
||||
@ -37,11 +39,30 @@ class CoffSectionHeader1 extends CoffSectionHeader {
|
||||
s_scnptr = reader.readNextInt();
|
||||
s_relptr = reader.readNextInt();
|
||||
s_lnnoptr = reader.readNextInt();
|
||||
s_nreloc = reader.readNextShort() & 0xffff;
|
||||
s_nlnno = reader.readNextShort() & 0xffff;
|
||||
s_flags = reader.readNextShort() & 0xffff;
|
||||
s_reserved = reader.readNextByte();
|
||||
s_page = reader.readNextByte();
|
||||
s_nreloc = reader.readNextUnsignedShort();
|
||||
s_nlnno = reader.readNextUnsignedShort();
|
||||
s_flags = reader.readNextUnsignedShort();
|
||||
s_reserved = (short) (reader.readNextByte() & 0xff);
|
||||
s_page = (short) (reader.readNextByte() & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws IOException {
|
||||
Structure struct = new StructureDataType(StructConverterUtil.parseName(getClass()), 0);
|
||||
struct.add(new ArrayDataType(ASCII, CoffConstants.SECTION_NAME_LENGTH, ASCII.getLength()),
|
||||
"s_name", null);
|
||||
struct.add(DWORD, "s_paddr", null);
|
||||
struct.add(DWORD, "s_vaddr", null);
|
||||
struct.add(DWORD, "s_size", null);
|
||||
struct.add(DWORD, "s_scnptr", null);
|
||||
struct.add(DWORD, "s_relptr", null);
|
||||
struct.add(DWORD, "s_lnnoptr", null);
|
||||
struct.add(WORD, "s_nreloc", null);
|
||||
struct.add(WORD, "s_nlnno", null);
|
||||
struct.add(WORD, "s_flags", null);
|
||||
struct.add(BYTE, "s_reserved", null);
|
||||
struct.add(BYTE, "s_page", null);
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package ghidra.app.util.bin.format.coff;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
/**
|
||||
* A 0x30 byte COFF section header
|
||||
@ -44,4 +46,23 @@ class CoffSectionHeader2 extends CoffSectionHeader {
|
||||
s_page = reader.readNextShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws IOException {
|
||||
Structure struct = new StructureDataType(StructConverterUtil.parseName(getClass()), 0);
|
||||
struct.add(new ArrayDataType(ASCII, CoffConstants.SECTION_NAME_LENGTH, ASCII.getLength()),
|
||||
"s_name", null);
|
||||
struct.add(DWORD, "s_paddr", null);
|
||||
struct.add(DWORD, "s_vaddr", null);
|
||||
struct.add(DWORD, "s_size", null);
|
||||
struct.add(DWORD, "s_scnptr", null);
|
||||
struct.add(DWORD, "s_relptr", null);
|
||||
struct.add(DWORD, "s_lnnoptr", null);
|
||||
struct.add(DWORD, "s_nreloc", null);
|
||||
struct.add(DWORD, "s_nlnno", null);
|
||||
struct.add(DWORD, "s_flags", null);
|
||||
struct.add(WORD, "s_reserved", null);
|
||||
struct.add(WORD, "s_page", null);
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package ghidra.app.util.bin.format.coff;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
/**
|
||||
* A 0x2c byte COFF section header
|
||||
@ -37,14 +39,32 @@ class CoffSectionHeader3 extends CoffSectionHeader {
|
||||
s_scnptr = reader.readNextInt();
|
||||
s_relptr = reader.readNextInt();
|
||||
s_lnnoptr = reader.readNextInt();
|
||||
s_nreloc = reader.readNextShort() & 0xffff;
|
||||
s_nlnno = reader.readNextShort() & 0xffff;
|
||||
s_nreloc = reader.readNextUnsignedShort();
|
||||
s_nlnno = reader.readNextUnsignedShort();
|
||||
s_flags = reader.readNextInt();
|
||||
|
||||
reader.readNextInt(); // section alignment, currently unused
|
||||
reader.readNextUnsignedInt(); // s_align: section alignment, currently unused
|
||||
|
||||
s_reserved = 0;
|
||||
s_page = 0;
|
||||
s_page = 0; // TODO: (short) (reader.readNextUnsignedByte() & 0xff) ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws IOException {
|
||||
Structure struct = new StructureDataType(StructConverterUtil.parseName(getClass()), 0);
|
||||
struct.add(new ArrayDataType(ASCII, CoffConstants.SECTION_NAME_LENGTH, ASCII.getLength()),
|
||||
"s_name", null);
|
||||
struct.add(DWORD, "s_paddr", null);
|
||||
struct.add(DWORD, "s_vaddr", null);
|
||||
struct.add(DWORD, "s_size", null);
|
||||
struct.add(DWORD, "s_scnptr", null);
|
||||
struct.add(DWORD, "s_relptr", null);
|
||||
struct.add(DWORD, "s_lnnoptr", null);
|
||||
struct.add(WORD, "s_nreloc", null);
|
||||
struct.add(WORD, "s_nlnno", null);
|
||||
struct.add(DWORD, "s_flags", null);
|
||||
struct.add(DWORD, "s_align", null);
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
||||
List<QueryResult> results =
|
||||
QueryOpinionService.query(getName(), header.getMachineName(), secondary);
|
||||
for (QueryResult result : results) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(true), result));
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(isMicrosoftFormat()), result));
|
||||
}
|
||||
if (loadSpecs.isEmpty()) {
|
||||
loadSpecs.add(new LoadSpec(this, header.getImageBase(false), true));
|
||||
|
@ -88,11 +88,15 @@ public class SymbolicPropogator {
|
||||
|
||||
// Cache instructions looked up by containing
|
||||
Map<Address, Instruction> instructionContainingCache = new LRUMap<>(LRU_SIZE);
|
||||
|
||||
// cache for pcode callother injection payloads
|
||||
HashMap<Long, InjectPayload> injectPayloadCache = new HashMap<Long, InjectPayload>();
|
||||
|
||||
public SymbolicPropogator(Program program) {
|
||||
this.program = program;
|
||||
|
||||
Language language = program.getLanguage();
|
||||
|
||||
programContext = new ProgramContextImpl(language);
|
||||
spaceContext = new ProgramContextImpl(language);
|
||||
|
||||
@ -777,16 +781,17 @@ public class SymbolicPropogator {
|
||||
|
||||
mustClearAll = pcodeIndex < mustClearAllUntil_PcodeIndex;
|
||||
|
||||
ptype = ops[pcodeIndex].getOpcode();
|
||||
Varnode out = ops[pcodeIndex].getOutput();
|
||||
Varnode[] in = ops[pcodeIndex].getInputs();
|
||||
PcodeOp pcodeOp = ops[pcodeIndex];
|
||||
ptype = pcodeOp.getOpcode();
|
||||
Varnode out = pcodeOp.getOutput();
|
||||
Varnode[] in = pcodeOp.getInputs();
|
||||
|
||||
Varnode val1, val2, val3, result;
|
||||
long lval1, lval2;
|
||||
long lresult;
|
||||
Varnode vt;
|
||||
if (debug) {
|
||||
Msg.info(this, " " + ops[pcodeIndex]);
|
||||
Msg.info(this, " " + pcodeOp);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -959,12 +964,12 @@ public class SymbolicPropogator {
|
||||
|
||||
// for callother, could be an interrupt, need to look at it like a call
|
||||
case PcodeOp.CALLOTHER:
|
||||
// HACK ALERT!
|
||||
// if this is a segment op, emulate the segmenting for now.
|
||||
String opName = this.program.getLanguage()
|
||||
.getUserDefinedOpName((int) in[0].getOffset());
|
||||
if (opName.equals("segment") && in.length > 2) {
|
||||
checkSegmented(out, in[1], in[2], mustClearAll);
|
||||
PcodeOp[] callOtherPcode = doCallOtherPcodeInjection(instruction, in, out);
|
||||
|
||||
if (callOtherPcode != null) {
|
||||
ops = injectPcode(ops, pcodeIndex, callOtherPcode);
|
||||
pcodeIndex = -1;
|
||||
injected = true;
|
||||
}
|
||||
else if (out != null) {
|
||||
// clear out settings for the output from call other.
|
||||
@ -1621,27 +1626,73 @@ public class SymbolicPropogator {
|
||||
return currentPcode;
|
||||
}
|
||||
|
||||
private void checkSegmented(Varnode out, Varnode in1, Varnode in2, boolean mustClearAll)
|
||||
throws NotFoundException {
|
||||
Varnode vval1 = context.getValue(in1, evaluator);
|
||||
Varnode vval2 = context.getValue(in2, evaluator);
|
||||
if (vval1.isConstant() && vval2.isConstant()) {
|
||||
int bitsize = program.getAddressFactory().getDefaultAddressSpace().getSize();
|
||||
long segBase;
|
||||
if (bitsize > 24) {
|
||||
segBase = context.getConstant(vval1, evaluator) << 16;
|
||||
}
|
||||
else if (bitsize == 24) {
|
||||
segBase = context.getConstant(vval1, evaluator) << 8;
|
||||
}
|
||||
else {
|
||||
segBase = context.getConstant(vval1, evaluator) << 4;
|
||||
}
|
||||
vval1 = context.createConstantVarnode(segBase, out.getSize());
|
||||
vval2 = context.createConstantVarnode(vval2.getOffset(), out.getSize());
|
||||
Varnode segmentedValue = context.add(vval1, vval2, evaluator);
|
||||
context.putValue(out, segmentedValue, mustClearAll);
|
||||
/**
|
||||
* Check for pcode replacement for a callother pcode op
|
||||
*
|
||||
* @param instr instruction whose pcodeop we might replace
|
||||
* @param ins input varnodes to callother pcodeop, ins[0] is callother nameindex
|
||||
* @param out output varnode for pcodeop
|
||||
* @return pcode that should replace callother, null otherwise
|
||||
*
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
private PcodeOp[] doCallOtherPcodeInjection(Instruction instr, Varnode ins[], Varnode out) throws NotFoundException {
|
||||
Program prog = instr.getProgram();
|
||||
|
||||
PcodeInjectLibrary snippetLibrary = prog.getCompilerSpec().getPcodeInjectLibrary();
|
||||
InjectPayload payload = findPcodeInjection(prog, snippetLibrary, ins[0].getOffset());
|
||||
// no injection defined for this call-other pcodeop
|
||||
if (payload == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<Varnode> inputs = new ArrayList<Varnode>();
|
||||
for (int i = 1; i < ins.length; i++) {
|
||||
Varnode vval = context.getValue(ins[i], evaluator);
|
||||
if (!vval.isConstant()) {
|
||||
return null;
|
||||
}
|
||||
inputs.add(vval);
|
||||
}
|
||||
|
||||
InjectContext con = snippetLibrary.buildInjectContext();
|
||||
con.baseAddr = instr.getMinAddress();
|
||||
con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset());
|
||||
con.callAddr = null;
|
||||
con.refAddr = con.callAddr;
|
||||
con.inputlist = inputs;
|
||||
con.output = new ArrayList<Varnode>();
|
||||
con.output.add(out);
|
||||
return payload.getPcode(prog, con);
|
||||
}
|
||||
|
||||
private InjectPayload findPcodeInjection(Program prog, PcodeInjectLibrary snippetLibrary, long callOtherIndex) {
|
||||
InjectPayload payload = (InjectPayload) injectPayloadCache.get(callOtherIndex);
|
||||
|
||||
// has a payload value for the pcode callother index
|
||||
if (payload != null) {
|
||||
return payload;
|
||||
}
|
||||
|
||||
// value null, if contains the key, then already looked up
|
||||
if (injectPayloadCache.containsKey(callOtherIndex)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String opName = prog.getLanguage().getUserDefinedOpName((int) callOtherIndex);
|
||||
|
||||
// segment is special named injection
|
||||
if ("segment".equals(opName)) {
|
||||
payload =
|
||||
snippetLibrary.getPayload(InjectPayload.EXECUTABLEPCODE_TYPE, "segment_pcode");
|
||||
}
|
||||
else {
|
||||
payload = snippetLibrary.getPayload(InjectPayload.CALLOTHERFIXUP_TYPE, opName);
|
||||
}
|
||||
|
||||
// save payload in cache for next lookup
|
||||
injectPayloadCache.put(callOtherIndex, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,8 +21,7 @@ import java.util.*;
|
||||
|
||||
import db.*;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.ClosedException;
|
||||
|
||||
/**
|
||||
@ -280,6 +279,10 @@ class OptionsDB extends AbstractOptions {
|
||||
if (optionType == getOptionType()) {
|
||||
value = optionType.convertStringToObject(rec.getString(VALUE_COL));
|
||||
}
|
||||
else {
|
||||
Msg.info(this, "The type for '" + this.getName() + "' has changed! Using default value.");
|
||||
value = getDefaultValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
isCached = true;
|
||||
|
Loading…
Reference in New Issue
Block a user