mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GT-3090_16bit_analysis'
This commit is contained in:
commit
23d1e9ad22
50 changed files with 1000 additions and 877 deletions
|
@ -79,6 +79,7 @@ public class SleighLanguage implements Language {
|
|||
* Non-null if a space should yes segmented addressing
|
||||
*/
|
||||
String segmentedspace = "";
|
||||
String segmentType = "";
|
||||
AddressSet volatileAddresses;
|
||||
private ContextCache contextcache = null;
|
||||
/**
|
||||
|
@ -100,6 +101,13 @@ public class SleighLanguage implements Language {
|
|||
initialize(description);
|
||||
}
|
||||
|
||||
private void addAdditionInject(InjectPayloadSleigh payload) {
|
||||
if (additionalInject == null) {
|
||||
additionalInject = new ArrayList<>();
|
||||
}
|
||||
additionalInject.add(payload);
|
||||
}
|
||||
|
||||
private void initialize(SleighLanguageDescription langDescription)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
this.defaultSymbols = new ArrayList<>();
|
||||
|
@ -508,6 +516,10 @@ public class SleighLanguage implements Language {
|
|||
if (nextElement != null) {
|
||||
XmlElement element = parser.start(); // segmented_address element
|
||||
segmentedspace = element.getAttribute("space");
|
||||
segmentType = element.getAttribute("type");
|
||||
if (segmentType == null) {
|
||||
segmentType = "";
|
||||
}
|
||||
}
|
||||
parser.dispose();
|
||||
}
|
||||
|
@ -586,20 +598,40 @@ public class SleighLanguage implements Language {
|
|||
}
|
||||
InjectPayloadSleigh payload =
|
||||
new InjectPayloadSleigh(subName, InjectPayload.EXECUTABLEPCODE_TYPE, source);
|
||||
if (additionalInject == null) {
|
||||
additionalInject = new ArrayList<>();
|
||||
}
|
||||
payload.restoreXml(parser);
|
||||
additionalInject.add(payload);
|
||||
addAdditionInject(payload);
|
||||
}
|
||||
}
|
||||
|
||||
public InjectPayloadSleigh parseSegmentOp(XmlElement el, XmlPullParser parser) {
|
||||
String name = el.getAttribute("userop");
|
||||
if (name == null) {
|
||||
name = "segment";
|
||||
}
|
||||
name = name + "_pcode";
|
||||
String source = "pspec: " + getLanguageID().getIdAsString();
|
||||
InjectPayloadSleigh payload = null;
|
||||
if (parser.peek().isStart()) {
|
||||
if (parser.peek().getName().equals("pcode")) {
|
||||
payload = new InjectPayloadSleigh(name, InjectPayload.EXECUTABLEPCODE_TYPE, source);
|
||||
payload.restoreXml(parser);
|
||||
}
|
||||
}
|
||||
while (parser.peek().isStart()) {
|
||||
parser.discardSubTree();
|
||||
}
|
||||
if (payload == null) {
|
||||
throw new SleighException("Missing <pcode> child for <segmentop> tag");
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
private void read(XmlPullParser parser) {
|
||||
Set<String> registerDataSet = new HashSet<>();
|
||||
|
||||
XmlElement element = parser.start("processor_spec");
|
||||
while (!parser.peek().isEnd()) {
|
||||
element = parser.start("properties", "segmented_address", "programcounter",
|
||||
element = parser.start("properties", "segmented_address", "segmentop", "programcounter",
|
||||
"data_space", "context_data", "volatile", "jumpassist", "incidentalcopy",
|
||||
"register_data", "default_symbols", "default_memory_blocks");
|
||||
if (element.getName().equals("properties")) {
|
||||
|
@ -769,6 +801,10 @@ public class SleighLanguage implements Language {
|
|||
parser.discardSubTree();
|
||||
}
|
||||
}
|
||||
else if (element.getName().equals("segmentop")) {
|
||||
InjectPayloadSleigh payload = parseSegmentOp(element, parser);
|
||||
addAdditionInject(payload);
|
||||
}
|
||||
// get rid of the end tag of whatever we started with at the top of the while
|
||||
parser.end(element);
|
||||
}
|
||||
|
@ -896,7 +932,12 @@ public class SleighLanguage implements Language {
|
|||
throw new SleighException(
|
||||
"Segmented space does not support truncation: " + name);
|
||||
}
|
||||
spc = new SegmentedAddressSpace(name, index);
|
||||
if (segmentType.equals("protected")) {
|
||||
spc = new ProtectedAddressSpace(name, index);
|
||||
}
|
||||
else {
|
||||
spc = new SegmentedAddressSpace(name, index);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (truncateSpace) {
|
||||
|
@ -1378,8 +1419,8 @@ public class SleighLanguage implements Language {
|
|||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique());
|
||||
|
||||
int size = element.getSize(); // Size in bits
|
||||
if (size == 20) {
|
||||
// TODO: SegmentedAddressSpace shouldn't really return 20
|
||||
if (element instanceof SegmentedAddressSpace) {
|
||||
// TODO: SegmentedAddressSpace shouldn't really return 21
|
||||
size = 32;
|
||||
}
|
||||
if (size > 64) {
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* ###
|
||||
* 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.address;
|
||||
|
||||
/**
|
||||
* Address Space for (intel) 16-bit protected mode programs. This space produces
|
||||
* SegmentedAddress objects whose underlying (flat) offset encodes both the
|
||||
* segment and the segment offset without losing information. There is no possibility
|
||||
* of alternate encodings for a single address as with real-mode.
|
||||
*/
|
||||
public class ProtectedAddressSpace extends SegmentedAddressSpace {
|
||||
|
||||
private final static int PROTECTEDMODE_SIZE = 32;
|
||||
private final static int PROTECTEDMODE_OFFSETSIZE = 16;
|
||||
|
||||
private int offsetSize; // Number of bits in the segment offset
|
||||
private long offsetMask; // Mask for retrieving the segment offset
|
||||
|
||||
public ProtectedAddressSpace(String name, int unique) {
|
||||
super(name, PROTECTEDMODE_SIZE, unique);
|
||||
offsetSize = PROTECTEDMODE_OFFSETSIZE;
|
||||
offsetMask = 1;
|
||||
offsetMask <<= offsetSize;
|
||||
offsetMask -= 1;
|
||||
maxAddress = getUncheckedAddress(maxOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getFlatOffset(int segment, long offset) {
|
||||
long res = segment;
|
||||
res <<= offsetSize;
|
||||
res += offset;
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultSegmentFromFlat(long flat) {
|
||||
return (int) (flat >>> offsetSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getDefaultOffsetFromFlat(long flat) {
|
||||
return (flat & offsetMask);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getOffsetFromFlat(long flat, int segment) {
|
||||
return (flat & offsetMask); // segment does not affect the offset
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SegmentedAddress getAddressInSegment(long flat, int preferredSegment) {
|
||||
return null; // The segment cannot be changed as the flat explicitly encodes it
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextOpenSegment(Address addr) {
|
||||
int res = getDefaultSegmentFromFlat(addr.getOffset());
|
||||
// Advance the selector by 8, accounting for the descriptor table bit and the privilege level bits
|
||||
res = (res + 8) & 0xfff8;
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -17,74 +17,56 @@ package ghidra.program.model.address;
|
|||
|
||||
|
||||
/**
|
||||
* Address class for dealing with intel 20 bit segmented addresses.
|
||||
* Address class for dealing with (intel) segmented addresses. The class itself is agnostic
|
||||
* about the mapping from segmented encoding to flat address offset, it uses the
|
||||
* SegmentedAddressSpace to perform this mapping. So the same class can be used to represent
|
||||
* either a real-mode address or a protected-mode address. The class uses the underlying
|
||||
* offset field to hold the flat encoding.
|
||||
*/
|
||||
public class SegmentedAddress extends GenericAddress {
|
||||
|
||||
private static final long serialVersionUID = 0;
|
||||
public static final int OFFSET_SIZE = 16;
|
||||
public static final int SEGMENT_SIZE = 16;
|
||||
|
||||
private final SegmentedAddressSpace addrSpace;
|
||||
private final int segment;
|
||||
private final int segment; // The specific segment value associated with this address
|
||||
|
||||
/**
|
||||
* Constructor for SegmentedAddress.
|
||||
* Offset is not validated against address space.
|
||||
* @param addrSpace address space for this address
|
||||
* @param offset offset into the space
|
||||
* @param addrSpace is the address space for this address
|
||||
* @param flat is the flat offset into the space
|
||||
*/
|
||||
SegmentedAddress(long offset, SegmentedAddressSpace addrSpace) {
|
||||
super(adjustOffset(offset), addrSpace);
|
||||
this.addrSpace = addrSpace;
|
||||
if (offset > 0xFFFFF) {
|
||||
this.segment = 0xFFFF;
|
||||
} else {
|
||||
this.segment = (int) ((offset >> 4) & 0xf000);
|
||||
}
|
||||
SegmentedAddress(long flat, SegmentedAddressSpace addrSpace) {
|
||||
super(adjustOffset(flat, addrSpace), addrSpace);
|
||||
segment = addrSpace.getDefaultSegmentFromFlat(flat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for SegmentedAddress.
|
||||
* @param addrSpace address space for this address
|
||||
* @param segmentOffset offset into the segment
|
||||
* @param overlayId overlay number
|
||||
* @param segment segment number
|
||||
* @param addrSpace is the address space for this address
|
||||
* @param segment is the segment number
|
||||
* @param segmentOffset is the offset into the segment
|
||||
* @throws AddressOutOfBoundsException if the address does not fit in the space
|
||||
*/
|
||||
SegmentedAddress(SegmentedAddressSpace addrSpace, int segment, int segmentOffset)
|
||||
throws AddressOutOfBoundsException {
|
||||
super(addrSpace, (segment << 4) + segmentOffset);
|
||||
this.addrSpace = addrSpace;
|
||||
if (offset > 0xFFFFF) {
|
||||
this.segment = 0xFFFF;
|
||||
} else {
|
||||
this.segment = segment;
|
||||
}
|
||||
super(addrSpace, addrSpace.getFlatOffset(segment, segmentOffset));
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for SegmentedAddress.
|
||||
* @param addrSpace address space for this address
|
||||
* @param offset offset into the space
|
||||
* @param flat is the flat offset into the space
|
||||
* @throws AddressOutOfBoundsException if the flat address does not fit in the space
|
||||
*/
|
||||
SegmentedAddress(SegmentedAddressSpace addrSpace, long offset)
|
||||
SegmentedAddress(SegmentedAddressSpace addrSpace, long flat)
|
||||
throws AddressOutOfBoundsException {
|
||||
super(addrSpace, adjustOffset(offset));
|
||||
this.addrSpace = addrSpace;
|
||||
if (offset > 0xFFFFF) {
|
||||
this.segment = 0xFFFF;
|
||||
} else {
|
||||
this.segment = (int) ((offset >> 4) & 0xf000);
|
||||
}
|
||||
super(addrSpace, adjustOffset(flat, addrSpace));
|
||||
segment = addrSpace.getDefaultSegmentFromFlat(flat);
|
||||
}
|
||||
|
||||
private static long adjustOffset(long offset) {
|
||||
// Decompiler treats segmented space as a 32-bit space and may produce an address offset
|
||||
// of 0xffffffff for a first use offset (= 0 minus 1).
|
||||
if (offset == 0x0ffffffffL) {
|
||||
offset = 0x0fffffL;
|
||||
}
|
||||
return offset;
|
||||
private static long adjustOffset(long flat, SegmentedAddressSpace addrSpace) {
|
||||
int seg = addrSpace.getDefaultSegmentFromFlat(flat);
|
||||
long offset = addrSpace.getDefaultOffsetFromFlat(flat);
|
||||
return addrSpace.getFlatOffset(seg, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,25 +79,24 @@ public class SegmentedAddress extends GenericAddress {
|
|||
|
||||
/**
|
||||
* Returns the offset within the segment.
|
||||
* @return the offset value
|
||||
*/
|
||||
public int getSegmentOffset() {
|
||||
return (int) (offset - (segment << 4));
|
||||
return (int) ((SegmentedAddressSpace) addrSpace).getOffsetFromFlat(offset, segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new address that is equivalent to this address using
|
||||
* the given segment number.
|
||||
* @param seg the seqment value to normalize to.
|
||||
* @return the new address
|
||||
*/
|
||||
public SegmentedAddress normalize(int seg) {
|
||||
if ((seg << 4) > offset) {
|
||||
SegmentedAddress res = ((SegmentedAddressSpace) addrSpace).getAddressInSegment(offset, seg);
|
||||
if (res == null) {
|
||||
return this;
|
||||
}
|
||||
int off = (int) (offset - (seg << 4));
|
||||
if (off > 0xffff) {
|
||||
return this;
|
||||
}
|
||||
return new SegmentedAddress(addrSpace, seg, off);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,8 +105,12 @@ public class SegmentedAddress extends GenericAddress {
|
|||
*/
|
||||
@Override
|
||||
public Address getNewAddress(long byteOffset) {
|
||||
SegmentedAddress segAddr = addrSpace.getAddress(byteOffset);
|
||||
return segAddr.normalize(segment);
|
||||
SegmentedAddressSpace segSpace = (SegmentedAddressSpace) addrSpace;
|
||||
SegmentedAddress res = segSpace.getAddressInSegment(byteOffset, segment);
|
||||
if (res == null) {
|
||||
return segSpace.getAddress(byteOffset);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -174,33 +159,4 @@ public class SegmentedAddress extends GenericAddress {
|
|||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.address.GenericAddress#next()
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address next() {
|
||||
if ((offset & SegmentedAddressSpace.MASK) == SegmentedAddressSpace.MASK) {
|
||||
return null;
|
||||
}
|
||||
long newOffset = (offset + 1) & SegmentedAddressSpace.MASK;
|
||||
return new SegmentedAddress(addrSpace, newOffset).normalize(segment);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.address.GenericAddress#previous()
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address previous() {
|
||||
if ((offset & SegmentedAddressSpace.MASK) == 0) {
|
||||
return null;
|
||||
}
|
||||
long newOffset = (offset - 1) & SegmentedAddressSpace.MASK;
|
||||
return new SegmentedAddress(addrSpace, newOffset).normalize(segment);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -20,30 +20,120 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import ghidra.util.NumericUtilities;
|
||||
|
||||
/**
|
||||
* Address Space for dealing with Intel 20 bit segmented addresses.
|
||||
* Address Space for dealing with (intel) segmented address spaces.
|
||||
* It understands the mapping between the segmented encoding (seg:offset) and
|
||||
* the flat address encoding necessary to produce an Address object that can be
|
||||
* used by other analyses. This mapping is inherent in protected methods:
|
||||
* - getDefaultOffsetFromFlat
|
||||
* - getDefaultSegmentFromFlat
|
||||
* - getFlatOffset
|
||||
* - getOffsetFromFlat
|
||||
* - getAddressInSegment
|
||||
*
|
||||
* These 5 methods can be overridden to get a different mapping. This base class is
|
||||
* set up to map as for x86 16-bit real-mode.
|
||||
*/
|
||||
public class SegmentedAddressSpace extends GenericAddressSpace {
|
||||
|
||||
private final static int SIZE = 21;
|
||||
|
||||
//private final static int SEGMENT_OFFSET_MASK = 0xffff;
|
||||
//final static long MASK = (1L << SIZE) - 1;
|
||||
private final static int REALMODE_SIZE = 21;
|
||||
private final static long REALMODE_MAXOFFSET = 0x10FFEF;
|
||||
|
||||
/**
|
||||
* Constructs a new Segmented AddressSpace.
|
||||
*
|
||||
* @param name
|
||||
* the name of the space
|
||||
* @param unique
|
||||
* the unique id for the space.
|
||||
* Constructor for larger size address spaces (than the real-mode space)
|
||||
* @param name is the name of the space
|
||||
* @param size is the number of bits in a (flat) address
|
||||
* @param unique is the unique id for the space
|
||||
*/
|
||||
protected SegmentedAddressSpace(String name, int size, int unique) {
|
||||
super(name, size, TYPE_RAM, unique);
|
||||
// maxAddress = getUncheckedAddress(maxOffset);
|
||||
// Constructors for derived classes that call this will
|
||||
// need to reconstruct maxAddress themselves.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Segmented AddressSpace for x86 real-mode, with 21-bit addresses.
|
||||
* @param name is the name of the space
|
||||
* @param unique is the unique id for the space.
|
||||
*/
|
||||
public SegmentedAddressSpace(String name, int unique) {
|
||||
super(name, SIZE, TYPE_RAM, unique);
|
||||
maxOffset = 0x10FFEF;
|
||||
super(name, REALMODE_SIZE, TYPE_RAM, unique);
|
||||
maxOffset = REALMODE_MAXOFFSET;
|
||||
spaceSize = maxOffset + 1;
|
||||
maxAddress = getUncheckedAddress(maxOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a 16-bit segment and an offset, produce the flat address offset
|
||||
* @param segment is the segment value
|
||||
* @param offset is the 16-bit offset into the segment
|
||||
* @return the encoded flat offset
|
||||
*/
|
||||
protected long getFlatOffset(int segment, long offset) {
|
||||
long res = segment;
|
||||
res <<= 4;
|
||||
res += offset;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a flat address offset, extract the default 16-bit segment portion
|
||||
* @param flat is the flat offset
|
||||
* @return the segment value
|
||||
*/
|
||||
protected int getDefaultSegmentFromFlat(long flat) {
|
||||
if (flat > 0xFFFFFL) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
return (int) ((flat >> 4) & 0xF000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a flat address offset, extract the offset portion assuming the
|
||||
* default segment.
|
||||
* @param flat is the flat offset
|
||||
* @return the offset value
|
||||
*/
|
||||
protected long getDefaultOffsetFromFlat(long flat) {
|
||||
if (flat > 0xFFFFFL) {
|
||||
return flat - 0xFFFF0;
|
||||
}
|
||||
return flat & 0xFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a flat address offset, extract a segment offset assuming a
|
||||
* specific segment value.
|
||||
* @param flat is the flat offset
|
||||
* @param segment is the specific segment value
|
||||
* @return the segment offset
|
||||
*/
|
||||
protected long getOffsetFromFlat(long flat, int segment) {
|
||||
return flat - (segment << 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a flat address offset and a preferred segment, try
|
||||
* to create an address that maps to the offset and is in the segment. For
|
||||
* architectures like x86 real-mode, multiple address encodings can map to
|
||||
* the same flat address offset. This method tries to select between the different
|
||||
* encodings. If the flat offset cannot be encoded with the preferred segment,
|
||||
* null is returned.
|
||||
*
|
||||
* @param flat is the flat offset
|
||||
* @param preferredSegment is the 16-bit preferred segment value
|
||||
* @return the segment encoded address or null
|
||||
*/
|
||||
protected SegmentedAddress getAddressInSegment(long flat, int preferredSegment) {
|
||||
if ((preferredSegment << 4) <= flat) {
|
||||
int off = (int) (flat - (preferredSegment << 4));
|
||||
if (off <= 0xffff) {
|
||||
return new SegmentedAddress(this, preferredSegment, off);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#getAddress(java.lang.String)
|
||||
|
@ -98,62 +188,16 @@ public class SegmentedAddressSpace extends GenericAddressSpace {
|
|||
long off = addr.getOffset() - displacement;
|
||||
if (off >= 0) {
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
return new SegmentedAddress(this, off).normalize(saddr.getSegment());
|
||||
Address resaddr = getAddressInSegment(off, saddr.getSegment());
|
||||
if (resaddr == null) { // Could not map into desired segment
|
||||
resaddr = new SegmentedAddress(this, off); // just use default
|
||||
}
|
||||
return resaddr;
|
||||
}
|
||||
throw new AddressOutOfBoundsException(
|
||||
"Address Overflow in subtract: " + addr + " + " + displacement);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#subtractWrap(ghidra.program.model.address.Address,
|
||||
* long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address subtractWrap(Address addr, long displacement) {
|
||||
|
||||
testAddressSpace(addr);
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
|
||||
int segOffset = (int) ((saddr.getSegmentOffset() - displacement) & SEGMENT_OFFSET_MASK);
|
||||
return new SegmentedAddress(this, saddr.getSegment(), segOffset);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.address.AbstractAddressSpace#subtractWrapSpace(ghidra.program.model.address.Address, long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address subtractWrapSpace(Address addr, long displacement) {
|
||||
testAddressSpace(addr);
|
||||
return new SegmentedAddress(this, (addr.getOffset() - displacement) & MASK);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#subtractNoWrap(ghidra.program.model.address.Address,
|
||||
* long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address subtractNoWrap(Address addr, long displacement) throws AddressOverflowException {
|
||||
|
||||
testAddressSpace(addr);
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
|
||||
long off = addr.getOffset() - displacement;
|
||||
if ((off & MASK) != off) {
|
||||
throw new AddressOverflowException();
|
||||
}
|
||||
|
||||
return new SegmentedAddress(this, off).normalize(saddr.getSegment());
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#add(ghidra.program.model.address.Address,
|
||||
|
@ -175,82 +219,35 @@ public class SegmentedAddressSpace extends GenericAddressSpace {
|
|||
//if ((off & MASK) == off) {
|
||||
if (off >= 0 && off <= maxOffset) {
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
return new SegmentedAddress(this, off).normalize(saddr.getSegment());
|
||||
Address resaddr = getAddressInSegment(off, saddr.getSegment());
|
||||
if (resaddr == null) { // Could not map into desired segment
|
||||
resaddr = new SegmentedAddress(this, off); // just use default
|
||||
}
|
||||
return resaddr;
|
||||
}
|
||||
throw new AddressOutOfBoundsException(
|
||||
"Address Overflow in add: " + addr + " + " + displacement);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#addWrap(ghidra.program.model.address.Address,
|
||||
* long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address addWrap(Address addr, long displacement) {
|
||||
testAddressSpace(addr);
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
|
||||
int segOffset = (int) ((saddr.getSegmentOffset() + displacement) & SEGMENT_OFFSET_MASK);
|
||||
return new SegmentedAddress(this, saddr.getSegment(), segOffset);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.address.AddressSpace#addWrapSpace(ghidra.program.model.address.Address,
|
||||
* long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address addWrapSpace(Address addr, long displacement) {
|
||||
testAddressSpace(addr);
|
||||
return new SegmentedAddress(this, (addr.getOffset() + displacement) & MASK);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#addNoWrap(ghidra.program.model.address.Address,
|
||||
* long)
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public Address addNoWrap(Address addr, long displacement) throws AddressOverflowException {
|
||||
|
||||
SegmentedAddress saddr = (SegmentedAddress) addr;
|
||||
testAddressSpace(addr);
|
||||
|
||||
long off = addr.getOffset() + displacement;
|
||||
if ((off & MASK) != off) {
|
||||
throw new AddressOverflowException();
|
||||
}
|
||||
|
||||
return new SegmentedAddress(this, off).normalize(saddr.getSegment());
|
||||
}
|
||||
*/
|
||||
|
||||
private long parseString(String addr) {
|
||||
if (addr.startsWith("0x") || addr.startsWith("0X")) {
|
||||
return NumericUtilities.parseHexLong(addr.substring(2));
|
||||
}
|
||||
return NumericUtilities.parseHexLong(addr);
|
||||
|
||||
}
|
||||
|
||||
private SegmentedAddress parseNonSegmented(String offStr) throws AddressFormatException {
|
||||
|
||||
try {
|
||||
long off = (int) parseString(offStr);
|
||||
if (off < 0 || off > 0xfffff) {
|
||||
throw new AddressFormatException("Offset is outside the range 0 to 0xfffff");
|
||||
}
|
||||
return new SegmentedAddress(this, off);
|
||||
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new AddressFormatException("Cannot parse (" + offStr + ") as a number.");
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
throw new AddressFormatException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private SegmentedAddress parseSegmented(String segStr, String offStr)
|
||||
|
@ -262,23 +259,22 @@ public class SegmentedAddressSpace extends GenericAddressSpace {
|
|||
catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
if (seg < 0 || seg > 0xffff) {
|
||||
throw new AddressFormatException("Segment is outside the range 0 to 0xffff");
|
||||
|
||||
int off = -1;
|
||||
try {
|
||||
off = (int) parseString(offStr);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new AddressFormatException(
|
||||
"Cannot parse (" + segStr + ':' + offStr + ") as a number.");
|
||||
}
|
||||
|
||||
try {
|
||||
int off = (int) parseString(offStr);
|
||||
if (off < 0 || off > 0xffff) {
|
||||
throw new AddressFormatException("Offset is outside the range 0 to 0xffff");
|
||||
}
|
||||
return new SegmentedAddress(this, seg, off);
|
||||
return getAddress(seg, off);
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
throw new AddressFormatException(e.getMessage());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new AddressFormatException("Cannot parse (" + offStr + ") as a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,12 +311,24 @@ public class SegmentedAddressSpace extends GenericAddressSpace {
|
|||
if (segmentOffset > 0xffff) {
|
||||
throw new AddressOutOfBoundsException("Offset is too large.");
|
||||
}
|
||||
if ((segment << 4) + segmentOffset > maxOffset) {
|
||||
throw new AddressOutOfBoundsException("Segmented address is too large.");
|
||||
if (segment > 0xffff) {
|
||||
throw new AddressOutOfBoundsException("Segment is too large.");
|
||||
}
|
||||
return new SegmentedAddress(this, segment, segmentOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the segment index for the first segment whose start address
|
||||
* comes after the given address
|
||||
* @param addr is the given address
|
||||
* @return the segment index
|
||||
*/
|
||||
public int getNextOpenSegment(Address addr) {
|
||||
int res = (int) addr.getOffset(); // The "flat" offset (presumably real-mode encoded)
|
||||
res = (res >> 4) + 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.address.AddressSpace#getPhysicalSpace()
|
||||
|
|
|
@ -163,29 +163,30 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
language.getProperty(GhidraLanguagePropertyKeys.PCODE_INJECT_LIBRARY_CLASS);
|
||||
if (classname == null) {
|
||||
pcodeInject = new PcodeInjectLibrary(language); // This is the default implementation
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class<?> c = Class.forName(classname);
|
||||
if (!PcodeInjectLibrary.class.isAssignableFrom(c)) {
|
||||
else {
|
||||
try {
|
||||
Class<?> c = Class.forName(classname);
|
||||
if (!PcodeInjectLibrary.class.isAssignableFrom(c)) {
|
||||
Msg.error(this,
|
||||
"Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.PCODE_INJECT_LIBRARY_CLASS);
|
||||
throw new RuntimeException(classname + " does not implement interface " +
|
||||
PcodeInjectLibrary.class.getName());
|
||||
}
|
||||
Class<? extends PcodeInjectLibrary> injectLibraryClass =
|
||||
(Class<? extends PcodeInjectLibrary>) c;
|
||||
Constructor<? extends PcodeInjectLibrary> constructor =
|
||||
injectLibraryClass.getConstructor(SleighLanguage.class);
|
||||
pcodeInject = constructor.newInstance(language);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this,
|
||||
"Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.PCODE_INJECT_LIBRARY_CLASS);
|
||||
throw new RuntimeException(classname + " does not implement interface " +
|
||||
PcodeInjectLibrary.class.getName());
|
||||
throw new RuntimeException("Failed to instantiate " + classname + " for language " +
|
||||
language.getLanguageID(), e);
|
||||
}
|
||||
Class<? extends PcodeInjectLibrary> injectLibraryClass =
|
||||
(Class<? extends PcodeInjectLibrary>) c;
|
||||
Constructor<? extends PcodeInjectLibrary> constructor =
|
||||
injectLibraryClass.getConstructor(SleighLanguage.class);
|
||||
pcodeInject = constructor.newInstance(language);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.PCODE_INJECT_LIBRARY_CLASS);
|
||||
throw new RuntimeException(
|
||||
"Failed to instantiate " + classname + " for language " + language.getLanguageID(),
|
||||
e);
|
||||
}
|
||||
List<InjectPayloadSleigh> additionalInject = language.getAdditionalInject();
|
||||
if (additionalInject != null) {
|
||||
|
@ -254,16 +255,6 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
ctxsetting.add(new ContextSetting(reg, value, begad, endad));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCallStackMod() {
|
||||
return defaultModel.getExtrapop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCallStackShift() {
|
||||
return defaultModel.getStackshift();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel[] getCallingConventions() {
|
||||
return models;
|
||||
|
@ -491,6 +482,12 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
evalCurrentPrototype = parser.start().getAttribute("name");
|
||||
parser.end();
|
||||
}
|
||||
else if (name.equals("segmentop")) {
|
||||
XmlElement el = parser.start();
|
||||
InjectPayloadSleigh payload = language.parseSegmentOp(el, parser);
|
||||
parser.end();
|
||||
pcodeInject.registerInject(payload);
|
||||
}
|
||||
else {
|
||||
XmlElement el = parser.start();
|
||||
parser.discardSubTree(el);
|
||||
|
|
|
@ -89,22 +89,6 @@ public interface CompilerSpec {
|
|||
*/
|
||||
public AddressSpace getStackBaseSpace();
|
||||
|
||||
/**
|
||||
* Number of extra bytes popped from the stack on return
|
||||
* -1 if it is unknown.
|
||||
* @return # of bytes popped from the stack by a called function on return.
|
||||
*/
|
||||
public int getCallStackMod();
|
||||
|
||||
/**
|
||||
* Get the normal shift in the stack at the call to this routine.
|
||||
* This will be the things pushed on the stack as part of the calling
|
||||
* conventions. Normally the return value.
|
||||
*
|
||||
* @return entry stack shift or -1 if it is unknown
|
||||
*/
|
||||
public int getCallStackShift();
|
||||
|
||||
/**
|
||||
* Returns true if stack grows with negative offsets
|
||||
*/
|
||||
|
|
|
@ -112,18 +112,19 @@ public class FunctionPrototype {
|
|||
// function pointer, in which case forcing the void
|
||||
// causes the decompiler to drop real parameters.
|
||||
// At the moment, we turn on varargs if there are no params
|
||||
if (voidimpliesdotdotdot && voidinputlock)
|
||||
if (voidimpliesdotdotdot && voidinputlock) {
|
||||
dotdotdot = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate Function Prototype from information attached to a function in the Program DB.
|
||||
*
|
||||
* @param f is the function to grab prototype from
|
||||
* @param default_extrapop
|
||||
* @param override_extrapop
|
||||
* @param overrideExtrapop is the override value to use for extrapop
|
||||
* @param doOverride is true if the override value should be used
|
||||
*/
|
||||
void grabFromFunction(Function f, int default_extrapop, boolean override_extrapop) {
|
||||
void grabFromFunction(Function f, int overrideExtrapop, boolean doOverride) {
|
||||
modelname = f.getCallingConventionName();
|
||||
modellock =
|
||||
((modelname != null) && (modelname != Function.UNKNOWN_CALLING_CONVENTION_STRING));
|
||||
|
@ -134,10 +135,12 @@ public class FunctionPrototype {
|
|||
returnstorage = returnparam.getVariableStorage();
|
||||
|
||||
SourceType sigSource = f.getSignatureSource();
|
||||
if (sigSource != SourceType.DEFAULT)
|
||||
if (sigSource != SourceType.DEFAULT) {
|
||||
outputlock = DataType.DEFAULT != returntype;
|
||||
else
|
||||
}
|
||||
else {
|
||||
outputlock = false;
|
||||
}
|
||||
|
||||
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
|
||||
outputlock = false;
|
||||
|
@ -157,12 +160,21 @@ public class FunctionPrototype {
|
|||
// stackshift is the normal stack change because of a call.
|
||||
//
|
||||
int purge = f.getStackPurgeSize();
|
||||
if (override_extrapop || purge == Function.INVALID_STACK_DEPTH_CHANGE ||
|
||||
purge == Function.UNKNOWN_STACK_DEPTH_CHANGE) {
|
||||
extrapop = default_extrapop;
|
||||
if (doOverride) {
|
||||
extrapop = overrideExtrapop;
|
||||
}
|
||||
else {
|
||||
extrapop = purge + f.getProgram().getCompilerSpec().getCallStackShift();
|
||||
PrototypeModel protoModel = f.getCallingConvention();
|
||||
if (protoModel == null) {
|
||||
protoModel = f.getProgram().getCompilerSpec().getDefaultCallingConvention();
|
||||
}
|
||||
if (purge == Function.INVALID_STACK_DEPTH_CHANGE ||
|
||||
purge == Function.UNKNOWN_STACK_DEPTH_CHANGE) {
|
||||
extrapop = protoModel.getExtrapop();
|
||||
}
|
||||
else {
|
||||
extrapop = purge + protoModel.getStackshift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,8 +199,9 @@ public class FunctionPrototype {
|
|||
* @return the number of defined parameters for this function prototype
|
||||
*/
|
||||
public int getNumParams() {
|
||||
if (localsyms != null)
|
||||
if (localsyms != null) {
|
||||
return localsyms.getNumParams();
|
||||
}
|
||||
return params.length;
|
||||
}
|
||||
|
||||
|
@ -198,8 +211,9 @@ public class FunctionPrototype {
|
|||
* if this prototype is not backed by a LocalSymbolMap
|
||||
*/
|
||||
public HighParam getParam(int i) {
|
||||
if (localsyms != null)
|
||||
if (localsyms != null) {
|
||||
return localsyms.getParam(i);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -299,36 +313,50 @@ public class FunctionPrototype {
|
|||
|
||||
/**
|
||||
* append an XML string representing this function prototype
|
||||
* @param res is where the string should be appended
|
||||
* @param dtmanage is the DataTypeManager for building type reference tags
|
||||
*/
|
||||
public void buildPrototypeXML(StringBuilder res, PcodeDataTypeManager dtmanage) {
|
||||
res.append("<prototype");
|
||||
if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP)
|
||||
if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) {
|
||||
SpecXmlUtils.encodeStringAttribute(res, "extrapop", "unknown");
|
||||
else
|
||||
}
|
||||
else {
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(res, "extrapop", extrapop);
|
||||
}
|
||||
SpecXmlUtils.encodeStringAttribute(res, "model", modelname);
|
||||
if (modellock)
|
||||
if (modellock) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "modellock", modellock);
|
||||
if (dotdotdot)
|
||||
}
|
||||
if (dotdotdot) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "dotdotdot", dotdotdot);
|
||||
if (voidinputlock)
|
||||
}
|
||||
if (voidinputlock) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "voidlock", voidinputlock);
|
||||
if (isinline)
|
||||
}
|
||||
if (isinline) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "inline", isinline);
|
||||
if (noreturn)
|
||||
}
|
||||
if (noreturn) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "noreturn", noreturn);
|
||||
if (custom)
|
||||
}
|
||||
if (custom) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "custom", custom);
|
||||
if (hasThis)
|
||||
}
|
||||
if (hasThis) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "hasthis", hasThis);
|
||||
if (isConstruct)
|
||||
}
|
||||
if (isConstruct) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "constructor", isConstruct);
|
||||
if (isDestruct)
|
||||
}
|
||||
if (isDestruct) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "destructor", isDestruct);
|
||||
}
|
||||
res.append(">\n");
|
||||
res.append(" <returnsym");
|
||||
if (outputlock)
|
||||
if (outputlock) {
|
||||
SpecXmlUtils.encodeBooleanAttribute(res, "typelock", outputlock);
|
||||
}
|
||||
res.append(">\n ");
|
||||
int sz = returntype.getLength();
|
||||
if (sz < 0) {
|
||||
|
@ -338,14 +366,16 @@ public class FunctionPrototype {
|
|||
if ((returnstorage != null) && returnstorage.isValid() &&
|
||||
(!returnstorage.isVoidStorage())) {
|
||||
int logicalsize = 0; // Assume logicalsize of return matches datatype size
|
||||
if (sz != returnstorage.size()) // If the sizes do not match
|
||||
if (sz != returnstorage.size()) { // If the sizes do no match
|
||||
logicalsize = sz; // force the logical size on the varnode
|
||||
}
|
||||
String addrstring = Varnode.buildXMLAddress(returnstorage.getVarnodes(), logicalsize);
|
||||
res.append(addrstring).append("\n ");
|
||||
}
|
||||
else
|
||||
else {
|
||||
// Decompiler will use model for storage
|
||||
res.append("<addr/>\n "); // Don't specify where return type is stored
|
||||
}
|
||||
|
||||
res.append(dtmanage.buildTypeRef(returntype, sz));
|
||||
res.append(" </returnsym>\n");
|
||||
|
@ -370,8 +400,9 @@ public class FunctionPrototype {
|
|||
res.append("\">\n");
|
||||
res.append(" <addr/>\n "); // Blank address
|
||||
sz = dt.getLength();
|
||||
if (sz < 0)
|
||||
if (sz < 0) {
|
||||
sz = 1;
|
||||
}
|
||||
res.append(dtmanage.buildTypeRef(dt, sz));
|
||||
res.append("</param>\n");
|
||||
}
|
||||
|
@ -381,21 +412,22 @@ public class FunctionPrototype {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse the function prototype from an XML tree node.
|
||||
*
|
||||
* @param node XML tree node from a parsing of a larger XML document
|
||||
*
|
||||
* @throws PcodeXMLException
|
||||
* Parse the function prototype from <prototype> tag.
|
||||
* @param parser is the XML document to parse
|
||||
* @param dtmanage is the DataTypeManager used to parse data-type tags
|
||||
* @throws PcodeXMLException for any problems parsing
|
||||
*/
|
||||
public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage)
|
||||
throws PcodeXMLException {
|
||||
XmlElement node = parser.start("prototype");
|
||||
modelname = node.getAttribute("model");
|
||||
String val = node.getAttribute("extrapop");
|
||||
if (val.equals("unknown"))
|
||||
if (val.equals("unknown")) {
|
||||
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||
else
|
||||
}
|
||||
else {
|
||||
extrapop = SpecXmlUtils.decodeInt(val);
|
||||
}
|
||||
modellock = false;
|
||||
if (node.hasAttribute("modellock")) {
|
||||
modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock"));
|
||||
|
@ -434,16 +466,18 @@ public class FunctionPrototype {
|
|||
}
|
||||
XmlElement retel = parser.start("returnsym");
|
||||
outputlock = false;
|
||||
if (retel.hasAttribute("typelock"))
|
||||
if (retel.hasAttribute("typelock")) {
|
||||
outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock"));
|
||||
}
|
||||
parser.discardSubTree();
|
||||
returnstorage = null; // For now don't use decompiler's return storage
|
||||
returntype = dtmanage.readXMLDataType(parser);
|
||||
parser.end(retel);
|
||||
|
||||
XmlElement peeknode = parser.peek();
|
||||
if ((peeknode != null) && peeknode.isStart())
|
||||
if ((peeknode != null) && peeknode.isStart()) {
|
||||
parser.discardSubTree(); // The decompiler may return an <inject> tag
|
||||
}
|
||||
parser.end(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
|
||||
/**
|
||||
* @param function function associated with the higher level function abstraction.
|
||||
* @param langParser language parser used to disassemble/get info on the language
|
||||
* @param language description of the processor language of the function
|
||||
* @param compilerSpec description of the compiler that produced the function
|
||||
* @param dtManager data type manager
|
||||
* @param showNamespace true signals to print function names with their namespace
|
||||
*/
|
||||
|
@ -124,33 +125,20 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
|
||||
/**
|
||||
* Populate the information for the HighFunction from the information stored in Ghidra attached
|
||||
* to the function.
|
||||
* Populate the information for the HighFunction from the information in the
|
||||
* Function object.
|
||||
*
|
||||
* @param default_extrapop
|
||||
* @param includeDefaultNames
|
||||
* @param override_extrapop
|
||||
* @param overrideExtrapop is the value to use if extrapop is overridden
|
||||
* @param includeDefaultNames is true if default symbol names should be considered locked
|
||||
* @param doOverride is true if extrapop is overridden
|
||||
*/
|
||||
public void grabFromFunction(int default_extrapop, boolean includeDefaultNames,
|
||||
boolean override_extrapop) {
|
||||
public void grabFromFunction(int overrideExtrapop, boolean includeDefaultNames,
|
||||
boolean doOverride) {
|
||||
localSymbols.grabFromFunction(includeDefaultNames); // Locals must be read first
|
||||
proto.grabFromFunction(func, default_extrapop, override_extrapop);
|
||||
proto.grabFromFunction(func, overrideExtrapop, doOverride);
|
||||
jumpTables = null;
|
||||
protoOverrides = null;
|
||||
grabOverrides();
|
||||
|
||||
// This reads any old actions from the StringProperty
|
||||
// This is needed for backward compatibility
|
||||
// String actstring = HighFunction.tagFindInclude("actionlist",funcstring);
|
||||
// if (actstring != null) {
|
||||
// try {
|
||||
// Element el = stringTree(actstring);
|
||||
// readActionXML(el,this);
|
||||
// } catch (PcodeXMLException e) {
|
||||
// Err.error(this, null, "Error", "Unexpected Exception: " + e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,10 +300,10 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
|
||||
/**
|
||||
* Read in the Jump Table list for this function from an XML rep
|
||||
* Read in the Jump Table list for this function from XML
|
||||
*
|
||||
* @param el
|
||||
* @throws PcodeXMLException
|
||||
* @param parser is the XML stream
|
||||
* @throws PcodeXMLException for any format errors
|
||||
*/
|
||||
private void readJumpTableListXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("jumptablelist");
|
||||
|
@ -425,11 +413,9 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
* @param high is the HighVariable to split
|
||||
* @param vn is a representative of the merge group to split out
|
||||
* @return a HighVariable containing just the forced merge group of vn
|
||||
* @throws PcodeException
|
||||
* @throws PcodeException if the split can't be performed
|
||||
*/
|
||||
public HighVariable splitOutMergeGroup(HighVariable high, Varnode vn) throws PcodeException {
|
||||
// if (high.isNameLocked() || high.isTypeLocked())
|
||||
// return high; // Locked variable should not be speculatively merged
|
||||
try {
|
||||
ArrayList<Varnode> newinst = new ArrayList<Varnode>();
|
||||
ArrayList<Varnode> oldinst = new ArrayList<Varnode>();
|
||||
|
@ -508,9 +494,13 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
|
||||
/**
|
||||
* Build an XML string that represents all the information about this HighFunction.
|
||||
* Build an XML string that represents all the information about this HighFunction. The
|
||||
* size describes how many bytes starting from the entry point are used by the function, but
|
||||
* this doesn't need to be strictly accurate as it is only used to associate the function with
|
||||
* addresses near its entry point.
|
||||
*
|
||||
* @param entryPoint pass null to use the function entryPoint, pass an address to force an entry point
|
||||
* @param size describes how many bytes the function occupies as code
|
||||
* @return the XML string
|
||||
*/
|
||||
public String buildFunctionXML(Address entryPoint, int size) {
|
||||
|
@ -588,28 +578,6 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
return resBuf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert old decompiler tags to new Register variables
|
||||
*/
|
||||
// public void updateVersion() {
|
||||
// StringPropertyMap stringmap = func.getProgram().getUsrPropertyManager().getStringPropertyMap(DECOMPILER_TAG_MAP);
|
||||
// String funcstring = null;
|
||||
// if (stringmap != null)
|
||||
// funcstring = stringmap.getString(func.getEntryPoint());
|
||||
//
|
||||
// String actstring = HighFunction.tagFindInclude("actionlist",funcstring);
|
||||
// if (actstring == null) return;
|
||||
// try {
|
||||
// Element el = stringTree(actstring);
|
||||
// readActionXML(el,this);
|
||||
// } catch (PcodeXMLException e) {
|
||||
// Err.error(this, null, "Error", "Unexpected Exception: " + e.getMessage(), e);
|
||||
// }
|
||||
// locals.grabFromFunction();
|
||||
// getLocalVariableMap().storeUnMappedToDatabase();
|
||||
// updateProperties();
|
||||
// }
|
||||
|
||||
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
||||
final String targetName) {
|
||||
return new ErrorHandler() {
|
||||
|
@ -708,14 +676,15 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create and XML SAX parse tree from an input XML string
|
||||
* Create XML parse tree from an input XML string
|
||||
*
|
||||
* TODO: this probably doesn't belong here.
|
||||
*
|
||||
* @param xml string to parse
|
||||
* @return an XML tree element
|
||||
* @param xml is the XML string to parse
|
||||
* @param handler is the handler to use for parsing errors
|
||||
* @return the XML tree
|
||||
*
|
||||
* @throws PcodeXMLException
|
||||
* @throws PcodeXMLException for format errors in the XML
|
||||
*/
|
||||
static public XmlPullParser stringTree(InputStream xml, ErrorHandler handler)
|
||||
throws PcodeXMLException {
|
||||
|
|
|
@ -539,16 +539,6 @@ class TemporaryCompilerSpec implements CompilerSpec {
|
|||
public void applyContextSettings(DefaultProgramContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCallStackMod() {
|
||||
return newCompilerSpec.getCallStackMod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCallStackShift() {
|
||||
return newCompilerSpec.getCallStackShift();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel[] getCallingConventions() {
|
||||
return new PrototypeModel[0];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue