mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 13:42:06 +00:00
Refactor SegmentedAddress preparing for protected mode
This commit is contained in:
parent
90f832bf1d
commit
cabe66e282
@ -21,70 +21,48 @@ package ghidra.program.model.address;
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.getSegmentFromFlat(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.getSegmentFromFlat(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.getSegmentFromFlat(flat);
|
||||
long offset = addrSpace.getOffsetFromFlat(flat);
|
||||
return addrSpace.getFlatOffset(seg, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,25 +75,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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 +101,12 @@ public class SegmentedAddress extends GenericAddress {
|
||||
*/
|
||||
@Override
|
||||
public Address getNewAddress(long byteOffset) {
|
||||
SegmentedAddress segAddr = addrSpace.getAddress(byteOffset);
|
||||
return segAddr.normalize(segment);
|
||||
SegmentedAddress res =
|
||||
((SegmentedAddressSpace) addrSpace).getAddressInSegment(byteOffset, segment);
|
||||
if (res == null) {
|
||||
return this;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -174,33 +155,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);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -26,16 +26,10 @@ 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;
|
||||
|
||||
/**
|
||||
* Constructs a new Segmented AddressSpace.
|
||||
*
|
||||
* @param name
|
||||
* the name of the space
|
||||
* @param unique
|
||||
* the unique id for the space.
|
||||
* @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);
|
||||
@ -44,6 +38,65 @@ public class SegmentedAddressSpace extends GenericAddressSpace {
|
||||
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 16-bit segment portion
|
||||
* @param flat is the flat offset
|
||||
* @return the segment value
|
||||
*/
|
||||
protected int getSegmentFromFlat(long flat) {
|
||||
if (flat > 0xFFFFFL) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
return (int) ((flat >> 4) & 0xF000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a flat address offset, extract the offset portion
|
||||
* @param flat is the flat offset
|
||||
* @return the offset value
|
||||
*/
|
||||
protected long getOffsetFromFlat(long flat) {
|
||||
if (flat > 0xFFFFFL) {
|
||||
return flat - 0xFFFF0;
|
||||
}
|
||||
return flat & 0xFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 +151,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,110 +182,56 @@ 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)
|
||||
throws AddressFormatException {
|
||||
int seg = -1;
|
||||
int off = -1;
|
||||
try {
|
||||
seg = (int) parseString(segStr);
|
||||
off = (int) parseString(offStr);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
if (seg < 0 || seg > 0xffff) {
|
||||
throw new AddressFormatException("Segment is outside the range 0 to 0xffff");
|
||||
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,8 +268,8 @@ 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user