diff --git a/Ghidra/Framework/SoftwareModeling/data/languages/processor_spec.rxg b/Ghidra/Framework/SoftwareModeling/data/languages/processor_spec.rxg index 3297f05c27..22e96e3f75 100644 --- a/Ghidra/Framework/SoftwareModeling/data/languages/processor_spec.rxg +++ b/Ghidra/Framework/SoftwareModeling/data/languages/processor_spec.rxg @@ -43,6 +43,9 @@ + + + diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java index 7bde62db52..e019267a1f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java @@ -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; /** @@ -508,6 +509,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(); } @@ -896,7 +901,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) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/ProtectedAddressSpace.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/ProtectedAddressSpace.java new file mode 100644 index 0000000000..d5634a5ae0 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/ProtectedAddressSpace.java @@ -0,0 +1,67 @@ +/* ### + * 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; + } + + @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 + } +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java index bec22700ed..9ba8cfa013 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddress.java @@ -17,11 +17,15 @@ 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 final int segment; + private final int segment; // The specific segment value associated with this address /** * Constructor for SegmentedAddress. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddressSpace.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddressSpace.java index 9c72cbd400..f999f56729 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddressSpace.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/SegmentedAddressSpace.java @@ -20,20 +20,46 @@ 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 REALMODE_SIZE = 21; + private final static long REALMODE_MAXOFFSET = 0x10FFEF; /** - * Constructs a new Segmented AddressSpace. + * 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); + spaceSize = 1; + spaceSize <<= size; + maxOffset = spaceSize - 1; + maxAddress = getUncheckedAddress(maxOffset); + } + + /** + * 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); }