Merge remote-tracking branch 'origin/patch'

Conflicts:
	Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java
	Ghidra/Framework/DB/src/main/java/db/DBHandle.java
This commit is contained in:
ghidra1 2020-12-09 15:05:16 -05:00
commit 066a7d0305
32 changed files with 920 additions and 129 deletions

View file

@ -195,7 +195,7 @@ public class GhidraState {
} }
/** /**
* Set the current selection and fire a {@link kProgramSelectionPluginEvent}. * Set the current selection and fire a {@link ProgramSelectionPluginEvent}.
* *
* @param selection the selection * @param selection the selection
*/ */

View file

@ -157,7 +157,7 @@ public interface ElfConstants {
/**No machine*/ /**No machine*/
public static final short EM_NONE = 0; public static final short EM_NONE = 0;
/** AT&T WE 32100 */ /** AT&T WE 32100 */
public static final short EM_M32 = 1; public static final short EM_M32 = 1;
/**SUN SPARC */ /**SUN SPARC */
public static final short EM_SPARC = 2; public static final short EM_SPARC = 2;

View file

@ -52,7 +52,7 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
} }
/** /**
* Returns the string for this type of reference (e.g., * or &) * Returns the string for this type of reference (e.g., * or &)
* @return the string * @return the string
*/ */
abstract protected String getTypeString(); abstract protected String getTypeString();

View file

@ -187,12 +187,12 @@ public class Pattern extends DittedBitSequence {
/** /**
* Read just the post patterns from the <patternpair> tags * Read just the post patterns from the <patternpair> tags
* @param file is the file to read from * @param file is the file to read from
* @param patternlist collects the resulting Pattern objects * @param patternList collects the resulting Pattern objects
* @param pfactory is the factory for constructing postrules and matchactions * @param pfactory is the factory for constructing postrules and matchactions
* @throws IOException * @throws IOException
* @throws SAXException * @throws SAXException
*/ */
public static void readPostPatterns(File file, ArrayList<Pattern> patlist, public static void readPostPatterns(File file, ArrayList<Pattern> patternList,
PatternFactory pfactory) throws SAXException, IOException { PatternFactory pfactory) throws SAXException, IOException {
ErrorHandler handler = new ErrorHandler() { ErrorHandler handler = new ErrorHandler() {
@Override @Override
@ -217,7 +217,7 @@ public class Pattern extends DittedBitSequence {
if (el.getName().equals("patternpairs")) { if (el.getName().equals("patternpairs")) {
PatternPairSet pairset = new PatternPairSet(); PatternPairSet pairset = new PatternPairSet();
pairset.restoreXml(parser, pfactory); pairset.restoreXml(parser, pfactory);
pairset.extractPostPatterns(patlist); pairset.extractPostPatterns(patternList);
} }
else { else {
parser.next(); parser.next();

View file

@ -87,30 +87,31 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
Address minAddr = program.getMinAddress(); Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress(); Address maxAddr = program.getMaxAddress();
setBytes(minAddr, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); setBytes(minAddr,
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 });
memBuf = new MemoryBufferImpl(program.getMemory(), minAddr); memBuf = new MemoryBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 4, 0); memBuf = new WrappedMemBuffer(memBuf, 4, 0);
byte[] bytes = new byte[6]; byte[] bytes = new byte[6];
// test get too many for cache // test get too many for cache
assertEquals(6, memBuf.getBytes(bytes, 2)); assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
// test not in buffer // test not in buffer
memBuf = new WrappedMemBuffer(memBuf, 6, 0); memBuf = new WrappedMemBuffer(memBuf, 6, 0);
assertEquals(6, memBuf.getBytes(bytes, 0)); assertEquals(6, memBuf.getBytes(bytes, 0));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 0, 1, 2, 3, 4, 5 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 0, 1, 2, 3, 4, 5 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 2)); assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 8)); assertEquals(6, memBuf.getBytes(bytes, 8));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 8, 9, 10, 11, 12, 13 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 8, 9, 10, 11, 12, 13 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 1)); assertEquals(6, memBuf.getBytes(bytes, 1));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 1, 2, 3, 4, 5, 6 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 1, 2, 3, 4, 5, 6 }, bytes);
assertEquals(10, memBuf.getByte(10)); assertEquals(10, memBuf.getByte(10));
assertEquals(0, memBuf.getByte(0)); assertEquals(0, memBuf.getByte(0));
@ -124,30 +125,31 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
Address minAddr = program.getMinAddress(); Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress(); Address maxAddr = program.getMaxAddress();
setBytes(minAddr, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); setBytes(minAddr,
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 });
memBuf = new MemoryBufferImpl(program.getMemory(), minAddr); memBuf = new MemoryBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 0, 0); memBuf = new WrappedMemBuffer(memBuf, 0, 0);
byte[] bytes = new byte[6]; byte[] bytes = new byte[6];
// test get too many for cache // test get too many for cache
assertEquals(6, memBuf.getBytes(bytes, 2)); assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
// test not in buffer // test not in buffer
memBuf = new WrappedMemBuffer(memBuf, 0, 0); memBuf = new WrappedMemBuffer(memBuf, 0, 0);
assertEquals(6, memBuf.getBytes(bytes, 0)); assertEquals(6, memBuf.getBytes(bytes, 0));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 0, 1, 2, 3, 4, 5 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 0, 1, 2, 3, 4, 5 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 2)); assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 8)); assertEquals(6, memBuf.getBytes(bytes, 8));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 8, 9, 10, 11, 12, 13 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 8, 9, 10, 11, 12, 13 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 1)); assertEquals(6, memBuf.getBytes(bytes, 1));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 1, 2, 3, 4, 5, 6 }, Assert.assertArrayEquals("Unexpected bytes read from memBuf",
bytes); new byte[] { 1, 2, 3, 4, 5, 6 }, bytes);
assertEquals(10, memBuf.getByte(10)); assertEquals(10, memBuf.getByte(10));
assertEquals(0, memBuf.getByte(0)); assertEquals(0, memBuf.getByte(0));
@ -155,6 +157,151 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
assertEquals(6, memBuf.getByte(6)); assertEquals(6, memBuf.getByte(6));
} }
@Test
public void testGetIntBuffered() throws Exception {
loadProgram("notepad");
int value;
Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress();
setBytes(minAddr, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 });
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 3, 0);
value = memBuf.getInt(0);
assertEquals(value, 0x00010203);
value = memBuf.getInt(1);
assertEquals(value, 0x01020304);
value = memBuf.getInt(3);
assertEquals(value, 0x03040506);
value = memBuf.getInt(8);
assertEquals(value, 0x08090A0B);
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 4, 0);
value = memBuf.getInt(0);
assertEquals(value, 0x00010203);
value = memBuf.getInt(1);
assertEquals(value, 0x01020304);
value = memBuf.getInt(3);
assertEquals(value, 0x03040506);
value = memBuf.getInt(8);
assertEquals(value, 0x08090A0B);
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 5, 0);
value = memBuf.getInt(0);
assertEquals(value, 0x00010203);
value = memBuf.getInt(1);
assertEquals(value, 0x01020304);
value = memBuf.getInt(3);
assertEquals(value, 0x03040506);
value = memBuf.getInt(8);
assertEquals(value, 0x08090A0B);
memBuf = new MemoryBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 3, 4);
value = memBuf.getInt(0);
assertEquals(value, 0x04050607);
value = memBuf.getInt(1);
assertEquals(value, 0x05060708);
value = memBuf.getInt(3);
assertEquals(value, 0x0708090A);
value = memBuf.getInt(8);
assertEquals(value, 0x0C0D0E0F);
memBuf = new MemoryBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 4, 4);
value = memBuf.getInt(0);
assertEquals(value, 0x04050607);
value = memBuf.getInt(1);
assertEquals(value, 0x05060708);
value = memBuf.getInt(3);
assertEquals(value, 0x0708090A);
value = memBuf.getInt(8);
assertEquals(value, 0x0C0D0E0F);
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 5, 4);
value = memBuf.getInt(0);
assertEquals(value, 0x04050607);
value = memBuf.getInt(1);
assertEquals(value, 0x05060708);
value = memBuf.getInt(3);
assertEquals(value, 0x0708090A);
value = memBuf.getInt(8);
assertEquals(value, 0x0C0D0E0F);
}
@Test
public void testGetShortBuffered() throws Exception {
loadProgram("notepad");
int value;
Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress();
setBytes(minAddr, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 });
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 3, 0);
value = memBuf.getShort(0);
assertEquals(value, 0x0001);
value = memBuf.getShort(1);
assertEquals(value, 0x0102);
value = memBuf.getShort(3);
assertEquals(value, 0x0304);
value = memBuf.getShort(8);
assertEquals(value, 0x0809);
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 5, 4);
value = memBuf.getShort(0);
assertEquals(value, 0x0405);
value = memBuf.getShort(1);
assertEquals(value, 0x0506);
value = memBuf.getShort(3);
assertEquals(value, 0x0708);
value = memBuf.getShort(8);
assertEquals(value, 0x0C0D);
}
@Test
public void testGetLongBuffered() throws Exception {
loadProgram("notepad");
long value;
Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress();
setBytes(minAddr, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 7, 0);
value = memBuf.getLong(0);
assertEquals(value, 0x0001020304050607L);
value = memBuf.getLong(1);
assertEquals(value, 0x0102030405060708L);
value = memBuf.getLong(3);
assertEquals(value, 0x030405060708090AL);
value = memBuf.getLong(8);
assertEquals(value, 0x08090A0B0C0D0E0FL);
memBuf = new DumbMemBufferImpl(program.getMemory(), minAddr);
memBuf = new WrappedMemBuffer(memBuf, 9, 4);
value = memBuf.getLong(0);
assertEquals(value, 0x0405060708090A0BL);
value = memBuf.getLong(1);
assertEquals(value, 0x05060708090A0B0CL);
value = memBuf.getLong(3);
assertEquals(value, 0x0708090A0B0C0D0EL);
value = memBuf.getLong(0);
assertEquals(value, 0x0405060708090A0BL);
}
private void setBytes(Address addr, byte[] bytes) throws MemoryAccessException { private void setBytes(Address addr, byte[] bytes) throws MemoryAccessException {
Memory mem = program.getMemory(); Memory mem = program.getMemory();

View file

@ -194,6 +194,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
Dimension sd = satelliteViewer.getSize(); Dimension sd = satelliteViewer.getSize();
java.awt.Point p = new java.awt.Point(vvd.width - sd.width, vvd.height - sd.height); java.awt.Point p = new java.awt.Point(vvd.width - sd.width, vvd.height - sd.height);
satelliteViewer.getComponent().setBounds(p.x, p.y, sd.width, sd.height); satelliteViewer.getComponent().setBounds(p.x, p.y, sd.width, sd.height);
satelliteViewer.scaleToLayout();
} }
}); });
@ -305,7 +306,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
new ActionBuilder("Reset View", ACTION_OWNER) new ActionBuilder("Reset View", ACTION_OWNER)
.description("Fit Graph to Window") .description("Fit Graph to Window")
.toolBarIcon(DefaultDisplayGraphIcons.FIT_TO_WINDOW) .toolBarIcon(DefaultDisplayGraphIcons.FIT_TO_WINDOW)
.onAction(context -> viewer.scaleToLayout()) .onAction(context -> centerAndScale())
.buildAndInstallLocal(componentProvider); .buildAndInstallLocal(componentProvider);
// create a button to show the view magnify lens // create a button to show the view magnify lens
@ -641,6 +642,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
graphDisplayProvider.setDefaultSatelliteState(selected); graphDisplayProvider.setDefaultSatelliteState(selected);
if (selected) { if (selected) {
viewer.getComponent().add(satelliteViewer.getComponent()); viewer.getComponent().add(satelliteViewer.getComponent());
satelliteViewer.scaleToLayout();
} }
else { else {
viewer.getComponent().remove(satelliteViewer.getComponent()); viewer.getComponent().remove(satelliteViewer.getComponent());
@ -827,6 +829,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
configureFilters(); configureFilters();
LayoutAlgorithm<AttributedVertex> initialLayoutAlgorithm = LayoutAlgorithm<AttributedVertex> initialLayoutAlgorithm =
layoutTransitionManager.getInitialLayoutAlgorithm(); layoutTransitionManager.getInitialLayoutAlgorithm();
initialLayoutAlgorithm.setAfter(() -> centerAndScale());
viewer.getVisualizationModel().setLayoutAlgorithm(initialLayoutAlgorithm); viewer.getVisualizationModel().setLayoutAlgorithm(initialLayoutAlgorithm);
}); });
componentProvider.setVisible(true); componentProvider.setVisible(true);
@ -979,6 +982,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
*/ */
public void centerAndScale() { public void centerAndScale() {
viewer.scaleToLayout(); viewer.scaleToLayout();
satelliteViewer.scaleToLayout();
} }
/** /**
@ -1080,7 +1084,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
public void ancestorAdded(AncestorEvent ancestorEvent) { public void ancestorAdded(AncestorEvent ancestorEvent) {
vv.getComponent().removeAncestorListener(this); vv.getComponent().removeAncestorListener(this);
Swing.runLater(() -> { Swing.runLater(() -> {
vv.scaleToLayout(); centerAndScale();
}); });
} }

View file

@ -530,6 +530,25 @@ public class TypeParser {
type = new UserDefinedTypeModuleSourceAndLineMsType(pdb, reader); type = new UserDefinedTypeModuleSourceAndLineMsType(pdb, reader);
//TODO: more work //TODO: more work
break; break;
case Class19MsType.PDB_ID:
type = new Class19MsType(pdb, reader);
break;
case Structure19MsType.PDB_ID:
type = new Structure19MsType(pdb, reader);
break;
// TODO: the following three types are only hypothetical and might be in the wrong
// order with the wrong PDB_IDs and the wrong internal elements and parsing.
// These are here as partial implementations until they are seen and can be
// cleaned up and put into service.
// case Union19MsType.PDB_ID:
// type = new Union19MsType(pdb, reader);
// break;
// case Enum19MsType.PDB_ID:
// type = new Enum19MsType(pdb, reader);
// break;
// case Interface19MsType.PDB_ID:
// type = new Interface19MsType(pdb, reader);
// break;
default: default:
// This should never happen (unless we missed something // This should never happen (unless we missed something
// or MSFT has added new in a version we do not handle. // or MSFT has added new in a version we do not handle.

View file

@ -26,8 +26,9 @@ import mdemangler.MDMang;
* Enums. * Enums.
*/ */
public abstract class AbstractComplexMsType extends AbstractMsType { public abstract class AbstractComplexMsType extends AbstractMsType {
// -1 is a flag to prevent the count from being emitted, which is what is desired if there
protected int count; // is not a count field for the child type. 0 and up are valid values.
protected int count = -1;
protected RecordNumber fieldDescriptorListRecordNumber; protected RecordNumber fieldDescriptorListRecordNumber;
protected MsProperty property; protected MsProperty property;
protected String name; protected String name;

View file

@ -110,8 +110,10 @@ public abstract class AbstractCompositeMsType extends AbstractComplexMsType {
myBuilder.append(" "); myBuilder.append(" ");
myBuilder.append(name); myBuilder.append(name);
myBuilder.append("<"); myBuilder.append("<");
if (count != -1) {
myBuilder.append(count); myBuilder.append(count);
myBuilder.append(","); myBuilder.append(",");
}
myBuilder.append(property); myBuilder.append(property);
myBuilder.append(">"); myBuilder.append(">");
AbstractMsType fieldType = getFieldDescriptorListType(); AbstractMsType fieldType = getFieldDescriptorListType();

View file

@ -72,8 +72,10 @@ public abstract class AbstractEnumMsType extends AbstractComplexMsType {
myBuilder.append(" "); myBuilder.append(" ");
myBuilder.append(name); myBuilder.append(name);
myBuilder.append("<"); myBuilder.append("<");
if (count != -1) {
myBuilder.append(count); myBuilder.append(count);
myBuilder.append(","); myBuilder.append(",");
}
myBuilder.append(pdb.getTypeRecord(underlyingRecordNumber)); myBuilder.append(pdb.getTypeRecord(underlyingRecordNumber));
myBuilder.append(","); myBuilder.append(",");
myBuilder.append(property); myBuilder.append(property);

View file

@ -0,0 +1,82 @@
/* ###
* 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.app.util.bin.format.pdb2.pdbreader.type;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
/*
* TODO this record type is a guess, using only data (no documentation) in its crafting.
* Thus, it can be cleaned up using trusted, msft-originated documentation if it becomes
* available and/or using more data analysis and/or non-trusted documentation.
* We are fairly certain that 0x1608 is some sort of class, but it could be a typedef class.
*/
/**
* This class represents the VS19 <B>MsType</B> flavor of C++ Class type. (At this time,
* PDB_ID is guessed to be a class similar to {@link ClassMsType}, eliminating
* the redundant count field, and adding other unknown field parsing.)
* <P>
* Note that class, struct, and interface are very closed related and have many of the same
* constructs and parsing procedures. However, they are separate. If any of the internals
* of one of these is changed, it is highly suggested that the others be changed as well as
* there is not code-shared between these other than by code duplication.
* <P>
* Note: we do not necessarily understand each of these data type classes. Refer to the
* base class for more information.
*/
public class Class19MsType extends AbstractClassMsType {
public static final int PDB_ID = 0x1608;
/**
* Constructor for this type.
* @param pdb {@link AbstractPdb} to which this type belongs.
* @param reader {@link PdbByteReader} from which this type is deserialized.
* @throws PdbException upon error parsing a field.
*/
public Class19MsType(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
property = new MsProperty(reader);
int x = reader.parseUnsignedShortVal(); //unknown
fieldDescriptorListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
derivedFromListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
vShapeTableRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
//TODO: has more... guessing below... commented out some other conditions, but we
// might want to investigate if any data hits them.
Numeric numericUnknown = new Numeric(reader); //unknown. Might even be just a short.
Numeric numeric = new Numeric(reader);
if (!numeric.isIntegral()) {
throw new PdbException("Expecting integral numeric");
}
size = numeric.getIntegral();
if (reader.hasMoreNonPad()) {
name = reader.parseString(pdb, StringParseType.StringNt);
if (reader.hasMoreNonPad()) {
mangledName = reader.parseString(pdb, StringParseType.StringNt);
}
// else if (reader.hasMore()) {
// }
}
// else {
// }
reader.skipPadding();
}
@Override
public int getPdbId() {
return PDB_ID;
}
}

View file

@ -0,0 +1,83 @@
/* ###
* 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.app.util.bin.format.pdb2.pdbreader.type;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
/*
* TODO this record type is a guess, using only data (no documentation) in its crafting.
* Thus, it can be cleaned up using trusted, msft-originated documentation if it becomes
* available and/or using more data analysis and/or non-trusted documentation.
* We believe there must be a union, enum, and interface (stubbed only guesses at PDB_IDs and can
* be incorrectly assigned) that are similar to the 0x1608 and 0x1609 class and struct classes,
* and yet similar to their older versions of union, enum, and interface as well.
*/
/**
* This class represents the VS19 <B>MsType</B> flavor of Enum type. (At this time,
* PDB_ID is guessed to be an enum similar to {@link EnumMsType}, eliminating
* the redundant count field, and adding other unknown field parsing.)
* <P>
* Note: we do not necessarily understand each of these data type classes. Refer to the
* base class for more information.
*/
public class Enum19MsType extends AbstractEnumMsType {
public static final int PDB_ID = 0x160b;
protected String mangledName;
/**
* Constructor for this type.
* @param pdb {@link AbstractPdb} to which this type belongs.
* @param reader {@link PdbByteReader} from which this type is deserialized.
* @throws PdbException upon error parsing a field.
*/
public Enum19MsType(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
property = new MsProperty(reader);
int x = reader.parseUnsignedShortVal(); //unknown
underlyingRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
fieldDescriptorListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
//TODO: has more... guessing below... commented out some other conditions, but we
// might want to investigate if any data hits them.
if (reader.hasMoreNonPad()) {
name = reader.parseString(pdb, StringParseType.StringNt);
if (reader.hasMoreNonPad()) {
// Additional parsing
mangledName = reader.parseString(pdb, StringParseType.StringNt);
}
// else if (reader.hasMore()) {
// }
}
// else {
// }
reader.skipPadding();
}
@Override
public int getPdbId() {
return PDB_ID;
}
/**
* Returns the mangled name field
* @return Mangled name.
*/
public String getMangledName() {
return mangledName;
}
}

View file

@ -0,0 +1,109 @@
/* ###
* 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.app.util.bin.format.pdb2.pdbreader.type;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
/*
* TODO this record type is a guess, using only data (no documentation) in its crafting.
* Thus, it can be cleaned up using trusted, msft-originated documentation if it becomes
* available and/or using more data analysis and/or non-trusted documentation.
* We believe there must be a union, enum, and interface (stubbed only guesses at PDB_IDs and can
* be incorrectly assigned) that are similar to the 0x1608 and 0x1609 class and struct classes,
* and yet similar to their older versions of union, enum, and interface as well.
* TODO: If this is a actual record type (for VS19), then we need to test it and to consider an
* abstract interface type (and also consider whether the emit should belong in the abstract
* composite type).
*/
/**
* This class represents the VS19 <B>MsType</B> flavor of Interface type. (At this time,
* PDB_ID is guessed to be a class similar to {@link InterfaceMsType}, eliminating
* the redundant count field, and adding other unknown field parsing.)
* <P>
* Note that class, struct, and interface are very closed related and have many of the same
* constructs and parsing procedures. However, they are separate. If any of the internals
* of one of these is changed, it is highly suggested that the others be changed as well as
* there is not code-shared between these other than by code duplication.
* <P>
* Note: we do not necessarily understand each of these data type classes. Refer to the
* base class for more information.
*/
public class Interface19MsType extends AbstractCompositeMsType {
public static final int PDB_ID = 0x160c;
private static final String TYPE_STRING = "interface";
/**
* Constructor for this type.
* @param pdb {@link AbstractPdb} to which this type belongs.
* @param reader {@link PdbByteReader} from which this type is deserialized.
* @throws PdbException upon error parsing a field.
*/
public Interface19MsType(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
property = new MsProperty(reader);
int x = reader.parseUnsignedShortVal(); //unknown
fieldDescriptorListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
derivedFromListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
vShapeTableRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
//TODO: has more... guessing below... commented out some other conditions, but we
// might want to investigate if any data hits them.
Numeric numericUnknown = new Numeric(reader); //unknown. Might even be just a short.
Numeric numeric = new Numeric(reader);
if (!numeric.isIntegral()) {
throw new PdbException("Expecting integral numeric");
}
size = numeric.getIntegral();
if (reader.hasMoreNonPad()) {
name = reader.parseString(pdb, StringParseType.StringNt);
if (reader.hasMoreNonPad()) {
mangledName = reader.parseString(pdb, StringParseType.StringNt);
}
// else if (reader.hasMore()) {
// }
}
// else {
// }
reader.skipPadding();
}
@Override
public int getPdbId() {
return PDB_ID;
}
@Override
public void emit(StringBuilder builder, Bind bind) {
StringBuilder myBuilder = new StringBuilder();
myBuilder.append(getTypeString());
myBuilder.append(" ");
myBuilder.append(name);
myBuilder.append("<");
myBuilder.append(property);
myBuilder.append(">");
AbstractMsType fieldType = getFieldDescriptorListType();
myBuilder.append(fieldType);
myBuilder.append(" ");
builder.insert(0, myBuilder);
}
@Override
protected String getTypeString() {
return TYPE_STRING;
}
}

View file

@ -0,0 +1,82 @@
/* ###
* 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.app.util.bin.format.pdb2.pdbreader.type;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
/*
* TODO this record type is a guess, using only data (no documentation) in its crafting.
* Thus, it can be cleaned up using trusted, msft-originated documentation if it becomes
* available and/or using more data analysis and/or non-trusted documentation.
* /We are fairly certain that 0x1609 is some sort of struct, but it could be a typedef struct.
*/
/**
* This class represents the VS19 <B>MsType</B> flavor of C/C++ Struct type. (At this time,
* PDB_ID is guessed to be a structure similar to {@link StructureMsType}, eliminating
* the redundant count field, and adding other unknown field parsing.)
* <P>
* Note that class, struct, and interface are very closed related and have many of the same
* constructs and parsing procedures. However, they are separate. If any of the internals
* of one of these is changed, it is highly suggested that the others be changed as well as
* there is not code-shared between these other than by code duplication.
* <P>
* Note: we do not necessarily understand each of these data type classes. Refer to the
* base class for more information.
*/
public class Structure19MsType extends AbstractStructureMsType {
public static final int PDB_ID = 0x1609;
/**
* Constructor for this type.
* @param pdb {@link AbstractPdb} to which this type belongs.
* @param reader {@link PdbByteReader} from which this type is deserialized.
* @throws PdbException upon error parsing a field.
*/
public Structure19MsType(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
property = new MsProperty(reader);
int x = reader.parseUnsignedShortVal(); //unknown
fieldDescriptorListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
derivedFromListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
vShapeTableRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
//TODO: has more... guessing below... commented out some other conditions, but we
// might want to investigate if any data hits them.
Numeric numericUnknown = new Numeric(reader); //unknown. Might even be just a short.
Numeric numeric = new Numeric(reader);
if (!numeric.isIntegral()) {
throw new PdbException("Expecting integral numeric");
}
size = numeric.getIntegral();
if (reader.hasMoreNonPad()) {
name = reader.parseString(pdb, StringParseType.StringNt);
if (reader.hasMoreNonPad()) {
mangledName = reader.parseString(pdb, StringParseType.StringNt);
}
// else if (reader.hasMore()) {
// }
}
// else {
// }
reader.skipPadding();
}
@Override
public int getPdbId() {
return PDB_ID;
}
}

View file

@ -0,0 +1,83 @@
/* ###
* 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.app.util.bin.format.pdb2.pdbreader.type;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
/*
* TODO this record type is a guess, using only data (no documentation) in its crafting.
* Thus, it can be cleaned up using trusted, msft-originated documentation if it becomes
* available and/or using more data analysis and/or non-trusted documentation.
* We believe there must be a union, enum, and interface (stubbed only guesses at PDB_IDs and can
* be incorrectly assigned) that are similar to the 0x1608 and 0x1609 class and struct classes,
* and yet similar to their older versions of union, enum, and interface as well.
*/
/**
* This class represents the VS19 <B>MsType</B> flavor of C/C++ Union type. (At this time,
* PDB_ID is guessed to be an enum similar to {@link EnumMsType}, eliminating
* the redundant count field, and adding other unknown field parsing.)
* <P>
* Note that class, struct, and interface are very closed related and have many of the same
* constructs and parsing procedures. However, they are separate. If any of the internals
* of one of these is changed, it is highly suggested that the others be changed as well as
* there is not code-shared between these other than by code duplication.
* <P>
* Note: we do not necessarily understand each of these data type classes. Refer to the
* base class for more information.
*/
public class Union19MsType extends AbstractUnionMsType {
public static final int PDB_ID = 0x160a;
/**
* Constructor for this type.
* @param pdb {@link AbstractPdb} to which this type belongs.
* @param reader {@link PdbByteReader} from which this type is deserialized.
* @throws PdbException upon error parsing a field.
*/
public Union19MsType(AbstractPdb pdb, PdbByteReader reader) throws PdbException {
super(pdb, reader);
property = new MsProperty(reader);
int x = reader.parseUnsignedShortVal(); //unknown
fieldDescriptorListRecordNumber = RecordNumber.parse(pdb, reader, RecordCategory.TYPE, 32);
// no derivedFromListRecordNumber or vShapeTableRecordNumber
//TODO: has more... guessing below... commented out some other conditions, but we
// might want to investigate if any data hits them.
Numeric numericUnknown = new Numeric(reader); //unknown. Might even be just a short.
Numeric numeric = new Numeric(reader);
if (!numeric.isIntegral()) {
throw new PdbException("Expecting integral numeric");
}
size = numeric.getIntegral();
if (reader.hasMoreNonPad()) {
name = reader.parseString(pdb, StringParseType.StringNt);
if (reader.hasMoreNonPad()) {
mangledName = reader.parseString(pdb, StringParseType.StringNt);
}
// else if (reader.hasMore()) {
// }
}
// else {
// }
reader.skipPadding();
}
@Override
public int getPdbId() {
return PDB_ID;
}
}

View file

@ -135,17 +135,37 @@ public class ArgumentsListTypeApplier extends MsTypeApplier {
DataType argDataType = argApplier.getDataType(); DataType argDataType = argApplier.getDataType();
if (argDataType == null) { if (argDataType == null) {
String message = applicator.appendLogMsg(
"PDB Warning: No type conversion for " + argApplier.getMsType().toString() + "PDB Warning: No type conversion for " + argApplier.getMsType().toString() +
" for parameter " + parameterCount + " of " + functionDefinition.getName(); " for parameter " + parameterCount + " of " + functionDefinition.getName());
applicator.appendLogMsg(message);
} }
else { else {
try {
ParameterDefinition parameterDefinition = ParameterDefinition parameterDefinition =
new ParameterDefinitionImpl(null, argDataType, ""); new ParameterDefinitionImpl(null, argDataType, "");
parameterDefinitionList.add(parameterDefinition); parameterDefinitionList.add(parameterDefinition);
parameterCount++; parameterCount++;
} }
catch (IllegalArgumentException e) {
try {
DataType substitute =
Undefined.getUndefinedDataType(argDataType.getLength());
ParameterDefinition parameterDefinition =
new ParameterDefinitionImpl(null, substitute, "");
parameterDefinitionList.add(parameterDefinition);
parameterCount++;
applicator.appendLogMsg("PDB Warning: Could not apply type " + argDataType +
" for parameter " + parameterCount + " of " +
functionDefinition.getName() + ". Using undefined type instead.");
}
catch (IllegalArgumentException e1) {
applicator.appendLogMsg("PDB Warning: Could not apply type " + argDataType +
" for parameter " + parameterCount + " of " +
functionDefinition.getName() + ". Undefined failed: " + e1);
}
}
}
} }
functionDefinition.setArguments(parameterDefinitionList.toArray( functionDefinition.setArguments(parameterDefinitionList.toArray(
new ParameterDefinition[parameterDefinitionList.size()])); new ParameterDefinition[parameterDefinitionList.size()]));

View file

@ -309,7 +309,8 @@ public class FunctionSymbolApplier extends MsSymbolApplier {
new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED); new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED);
if (!sigCmd.applyTo(applicator.getProgram(), monitor)) { if (!sigCmd.applyTo(applicator.getProgram(), monitor)) {
applicator.appendLogMsg( applicator.appendLogMsg(
"failed to apply signature to function at address " + address.toString()); "PDB Warning: Failed to apply signature to function at address " + address +
" due to " + sigCmd.getStatusMsg() + "; dataType: " + def.getName());
return false; return false;
} }
} }

View file

@ -552,8 +552,7 @@ public class PdbApplicator {
int num = pdb.getDebugInfo().getNumModules(); int num = pdb.getDebugInfo().getNumModules();
for (int index = 1; index <= num; index++) { for (int index = 1; index <= num; index++) {
monitor.checkCanceled(); monitor.checkCanceled();
String moduleName = String moduleName = pdb.getDebugInfo().getModuleInformation(index).getModuleName();
pdb.getDebugInfo().getModuleInformation(index).getModuleName();
categoryNames.add(moduleName); categoryNames.add(moduleName);
} }
@ -1266,7 +1265,9 @@ public class PdbApplicator {
NamespaceUtils.getNonFunctionNamespace(program, path.getParent()); NamespaceUtils.getNonFunctionNamespace(program, path.getParent());
if (parentNamespace == null) { if (parentNamespace == null) {
String type = isClass ? "class" : "namespace"; String type = isClass ? "class" : "namespace";
log.appendMsg("Error: failed to define " + type + ": " + path); log.appendMsg(
"PDB Warning: Because parent namespace does not exist, failed to define " +
type + ": " + path);
continue; continue;
} }
defineNamespace(parentNamespace, path.getName(), isClass); defineNamespace(parentNamespace, path.getName(), isClass);
@ -1294,7 +1295,8 @@ public class PdbApplicator {
else if (namespace.getSymbol().getSymbolType() == SymbolType.NAMESPACE) { else if (namespace.getSymbol().getSymbolType() == SymbolType.NAMESPACE) {
return; return;
} }
log.appendMsg("Unable to create class namespace due to conflicting symbol: " + log.appendMsg(
"PDB Warning: Unable to create class namespace due to conflicting symbol: " +
namespace.getName(true)); namespace.getName(true));
} }
else if (isClass) { else if (isClass) {
@ -1305,8 +1307,9 @@ public class PdbApplicator {
} }
} }
catch (InvalidInputException | DuplicateNameException e) { catch (InvalidInputException | DuplicateNameException e) {
log.appendMsg("Unable to create class namespace: " + parentNamespace.getName(true) + log.appendMsg(
Namespace.DELIMITER + name + " due to exception: " + e.toString()); "PDB Warning: Unable to create class namespace due to exception: " + e.toString() +
"; Namespace: " + parentNamespace.getName(true) + Namespace.DELIMITER + name);
} }
} }
@ -1407,7 +1410,7 @@ public class PdbApplicator {
return true; return true;
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
log.appendMsg("Unable to create symbol: " + e.getMessage()); log.appendMsg("PDB Warning: Unable to create symbol: " + e.getMessage());
} }
return false; return false;
} }
@ -1532,7 +1535,8 @@ public class PdbApplicator {
namespace, name, SourceType.IMPORTED); namespace, name, SourceType.IMPORTED);
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
appendLogMsg("Unable to create symbol " + symbolPathString + " at " + address); log.appendMsg("PDB Warning: Unable to create symbol at " + address +
" due to exception: " + e.toString() + "; symbolPathName: " + symbolPathString);
} }
return symbol; return symbol;
} }

View file

@ -93,11 +93,13 @@ public class PointerTypeApplier extends MsTypeApplier {
if (underlyingType == null) { if (underlyingType == null) {
// TODO: we have seen underlyingTypeApplier is for NoTypeApplier for VtShapeMsType // TODO: we have seen underlyingTypeApplier is for NoTypeApplier for VtShapeMsType
// Figure it out, and perhaps create an applier that creates a structure or something? // Figure it out, and perhaps create an applier that creates a structure or something?
return new VoidDataType(applicator.getDataTypeManager()); underlyingType = applicator.getPdbPrimitiveTypeApplicator().getVoidType();
// throw new PdbException("Underlying type missing for pointer."); applicator.appendLogMsg(
"PDB Warning: No type conversion for " + underlyingApplier.getMsType().toString() +
" as underlying type for pointer. Using void.");
} }
int size = getSizeInt(); int size = type.getSize().intValueExact();
if (size == applicator.getDataOrganization().getPointerSize()) { if (size == applicator.getDataOrganization().getPointerSize()) {
size = -1; // Use default size = -1; // Use default
} }

View file

@ -494,6 +494,29 @@ public class TypeApplierFactory {
case UserDefinedTypeModuleSourceAndLineMsType.PDB_ID: case UserDefinedTypeModuleSourceAndLineMsType.PDB_ID:
applier = new UdtSourceLineTypeApplier(applicator, type); applier = new UdtSourceLineTypeApplier(applicator, type);
break; break;
case Class19MsType.PDB_ID:
applier = new CompositeTypeApplier(applicator, (Class19MsType) type);
break;
case Structure19MsType.PDB_ID:
applier = new CompositeTypeApplier(applicator, (Structure19MsType) type);
break;
// TODO: the following three types are only hypothetical and might be in the wrong
// order with the wrong PDB_IDs and the wrong internal elements and parsing.
// These are here as partial implementations until they are seen and can be
// cleaned up and put into service.
// case Union19MsType.PDB_ID:
// applier = new CompositeTypeApplier(applicator, (Union19MsType) type);
// break;
// case Enum19MsType.PDB_ID:
// applier = new EnumTypeApplier(applicator, (Enum19MsType) type);
// break;
// case Interface19MsType.PDB_ID:
// // TODO InterfaceTypeApplier does not exist, and the two types we would
// // want to send it would need to either be abstracted to one abstract type
// // or a generic AbstractMsType would have to be sent and then verified
// // internal to the applier.
// applier = new InterfaceTypeApplier(applicator, (Interface19MsType) type);
// break;
// If all of the above are enabled, this should never happen (unless we missed // If all of the above are enabled, this should never happen (unless we missed
// something or MSFT has added new in a version we do not handle. // something or MSFT has added new in a version we do not handle.

View file

@ -401,6 +401,29 @@ public class TypesTest extends AbstractGenericTest {
assertEquals("class ClassName<2,packed ctor>DummyMsType", result); assertEquals("class ClassName<2,packed ctor>DummyMsType", result);
} }
//TODO: Might need adjusting fields of record are understood.
@Test
public void testClass19MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Class19MsType.PDB_ID);
byte[] propertyBuffer = createMsPropertyBuffer();
writer.putBytes(propertyBuffer);
writer.putUnsignedShort(0); // unknown field
writer.putUnsignedInt(4096); // Type index of field descriptor list.
writer.putUnsignedInt(4096); // If not zero, is type index of derived-from list
writer.putUnsignedInt(vtShapeMsType1); // Type index of the VtShapeMsType (vshape table).
writer.putNumeric(new BigInteger("0", 16), 0x8002); // unk field. Not sure if Numeric
writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of class.
writer.putNullTerminatedString("ClassName");
writer.putNullTerminatedString("OtherName");
writer.putAlign(2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsType type = typeParser.parse(reader);
assertEquals(type instanceof Class19MsType, true);
String result = type.toString().trim();
assertEquals("class ClassName<packed ctor>DummyMsType", result);
}
@Test @Test
public void testStructure16MsType() throws Exception { public void testStructure16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
@ -463,6 +486,29 @@ public class TypesTest extends AbstractGenericTest {
assertEquals("struct StructureName<2,packed ctor>DummyMsType", result); assertEquals("struct StructureName<2,packed ctor>DummyMsType", result);
} }
//TODO: Might need adjusting fields of record are understood.
@Test
public void testStructure19MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Structure19MsType.PDB_ID);
byte[] propertyBuffer = createMsPropertyBuffer();
writer.putBytes(propertyBuffer);
writer.putUnsignedShort(0); // unknown field
writer.putUnsignedInt(4096); // Type index of field descriptor list.
writer.putUnsignedInt(4096); // If not zero, is type index of derived-from list
writer.putUnsignedInt(vtShapeMsType1); // Type index of the VtShapeMsType (vshape table).
writer.putNumeric(new BigInteger("0", 16), 0x8002); // unk field. Not sure if Numeric
writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of structure.
writer.putNullTerminatedString("StructureName");
writer.putNullTerminatedString("OtherName");
writer.putAlign(2);
PdbByteReader reader = new PdbByteReader(writer.get());
AbstractMsType type = typeParser.parse(reader);
assertEquals(type instanceof Structure19MsType, true);
String result = type.toString().trim();
assertEquals("struct StructureName<packed ctor>DummyMsType", result);
}
@Test @Test
public void testInterfaceMsType() throws Exception { public void testInterfaceMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
@ -484,15 +530,38 @@ public class TypesTest extends AbstractGenericTest {
assertEquals("interface InterfaceName<2,packed ctor>DummyMsType", result); assertEquals("interface InterfaceName<2,packed ctor>DummyMsType", result);
} }
//TODO: Hypothetical type... will need adjusting as record type is adjusted.
// @Test
// public void testInterface19MsType() throws Exception {
// PdbByteWriter writer = new PdbByteWriter();
// writer.putUnsignedShort(Interface19MsType.PDB_ID);
// byte[] propertyBuffer = createMsPropertyBuffer();
// writer.putBytes(propertyBuffer);
// writer.putUnsignedShort(0); // unknown field
// writer.putUnsignedInt(4096); // Type index of field descriptor list.
// writer.putUnsignedInt(4096); // If not zero, is type index of derived-from list
// writer.putUnsignedInt(vtShapeMsType1); // Type index of the VtShapeMsType (vshape table).
// writer.putNumeric(new BigInteger("0", 16), 0x8002); // unk field. Not sure if Numeric
// writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of interface.
// writer.putNullTerminatedString("InterfaceName");
// writer.putNullTerminatedString("OtherName");
// writer.putAlign(2);
// PdbByteReader reader = new PdbByteReader(writer.get());
// AbstractMsType type = typeParser.parse(reader);
// assertEquals(type instanceof Interface19MsType, true);
// String result = type.toString().trim();
// assertEquals("interface InterfaceName<packed ctor>DummyMsType", result);
// }
@Test @Test
public void testUnion16MsType() throws Exception { public void testUnion16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(Union16MsType.PDB_ID); writer.putUnsignedShort(Union16MsType.PDB_ID);
writer.putUnsignedShort(2); // Count of number of elements in the class. writer.putUnsignedShort(2); // Count of number of elements in the union.
writer.putUnsignedShort(4096); // Type index of field descriptor list. writer.putUnsignedShort(4096); // Type index of field descriptor list.
byte[] propertyBuffer = createMsPropertyBuffer(); byte[] propertyBuffer = createMsPropertyBuffer();
writer.putBytes(propertyBuffer); writer.putBytes(propertyBuffer);
writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of class. writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of union.
writer.putByteLengthPrefixedString("UnionName16"); writer.putByteLengthPrefixedString("UnionName16");
writer.putPadding(2); writer.putPadding(2);
PdbByteReader reader = new PdbByteReader(writer.get()); PdbByteReader reader = new PdbByteReader(writer.get());
@ -506,11 +575,11 @@ public class TypesTest extends AbstractGenericTest {
public void testUnionStMsType() throws Exception { public void testUnionStMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(UnionStMsType.PDB_ID); writer.putUnsignedShort(UnionStMsType.PDB_ID);
writer.putUnsignedShort(2); // Count of number of elements in the class. writer.putUnsignedShort(2); // Count of number of elements in the union.
byte[] propertyBuffer = createMsPropertyBuffer(); byte[] propertyBuffer = createMsPropertyBuffer();
writer.putBytes(propertyBuffer); writer.putBytes(propertyBuffer);
writer.putUnsignedInt(4096); // Type index of field descriptor list. writer.putUnsignedInt(4096); // Type index of field descriptor list.
writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of class. writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of union.
writer.putByteLengthPrefixedString("UnionNameSt"); writer.putByteLengthPrefixedString("UnionNameSt");
writer.putByteLengthPrefixedString("OtherNameSt"); writer.putByteLengthPrefixedString("OtherNameSt");
writer.putAlign(2); writer.putAlign(2);
@ -525,11 +594,11 @@ public class TypesTest extends AbstractGenericTest {
public void testUnionMsType() throws Exception { public void testUnionMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
writer.putUnsignedShort(UnionMsType.PDB_ID); writer.putUnsignedShort(UnionMsType.PDB_ID);
writer.putUnsignedShort(2); // Count of number of elements in the class. writer.putUnsignedShort(2); // Count of number of elements in the union.
byte[] propertyBuffer = createMsPropertyBuffer(); byte[] propertyBuffer = createMsPropertyBuffer();
writer.putBytes(propertyBuffer); writer.putBytes(propertyBuffer);
writer.putUnsignedInt(4096); // Type index of field descriptor list. writer.putUnsignedInt(4096); // Type index of field descriptor list.
writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of class. writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of union.
writer.putNullTerminatedString("UnionName"); writer.putNullTerminatedString("UnionName");
writer.putNullTerminatedString("OtherName"); writer.putNullTerminatedString("OtherName");
writer.putAlign(2); writer.putAlign(2);
@ -540,6 +609,27 @@ public class TypesTest extends AbstractGenericTest {
assertEquals("union UnionName<2,packed ctor>DummyMsType", result); assertEquals("union UnionName<2,packed ctor>DummyMsType", result);
} }
//TODO: Hypothetical type... will need adjusting as record type is adjusted.
// @Test
// public void testUnion19MsType() throws Exception {
// PdbByteWriter writer = new PdbByteWriter();
// writer.putUnsignedShort(Union19MsType.PDB_ID);
// byte[] propertyBuffer = createMsPropertyBuffer();
// writer.putBytes(propertyBuffer);
// writer.putUnsignedShort(0); // unknown field
// writer.putUnsignedInt(4096); // Type index of field descriptor list.
// writer.putNumeric(new BigInteger("0", 16), 0x8002); // unk field. Not sure if Numeric
// writer.putNumeric(new BigInteger("10", 16), 0x8002); // size of union.
// writer.putNullTerminatedString("UnionName");
// writer.putNullTerminatedString("OtherName");
// writer.putAlign(2);
// PdbByteReader reader = new PdbByteReader(writer.get());
// AbstractMsType type = typeParser.parse(reader);
// assertEquals(type instanceof Union19MsType, true);
// String result = type.toString().trim();
// assertEquals("union UnionName<packed ctor>DummyMsType", result);
// }
@Test @Test
public void testEnum16MsType() throws Exception { public void testEnum16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();
@ -596,6 +686,26 @@ public class TypesTest extends AbstractGenericTest {
assertEquals("enum EnumName<2,DummyMsType,packed ctor>DummyMsType", result); assertEquals("enum EnumName<2,DummyMsType,packed ctor>DummyMsType", result);
} }
//TODO: Hypothetical type... will need adjusting as record type is adjusted.
// @Test
// public void testEnum19MsType() throws Exception {
// PdbByteWriter writer = new PdbByteWriter();
// writer.putUnsignedShort(Enum19MsType.PDB_ID);
// byte[] propertyBuffer = createMsPropertyBuffer();
// writer.putBytes(propertyBuffer);
// writer.putUnsignedShort(0); // unknown field
// writer.putUnsignedInt(4096); // Underlying type index.
// writer.putUnsignedInt(4096); // Type index of field descriptor list.
// writer.putNullTerminatedString("EnumName");
// writer.putNullTerminatedString("OtherName");
// writer.putAlign(2);
// PdbByteReader reader = new PdbByteReader(writer.get());
// AbstractMsType type = typeParser.parse(reader);
// assertEquals(type instanceof Enum19MsType, true);
// String result = type.toString().trim();
// assertEquals("enum EnumName<DummyMsType,packed ctor>DummyMsType", result);
// }
@Test @Test
public void testProcedure16MsType() throws Exception { public void testProcedure16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter(); PdbByteWriter writer = new PdbByteWriter();

View file

@ -54,6 +54,7 @@ public class DBHandle {
/** /**
* Construct a temporary database handle. * Construct a temporary database handle.
* The saveAs method must be used to save the database. * The saveAs method must be used to save the database.
* @throws IOException if a IO error occurs
*/ */
public DBHandle() throws IOException { public DBHandle() throws IOException {
this(BufferMgr.DEFAULT_BUFFER_SIZE, BufferMgr.DEFAULT_CACHE_SIZE); this(BufferMgr.DEFAULT_BUFFER_SIZE, BufferMgr.DEFAULT_CACHE_SIZE);
@ -62,18 +63,23 @@ public class DBHandle {
/** /**
* Construct a temporary database handle. * Construct a temporary database handle.
* The saveAs method must be used to save the database. * The saveAs method must be used to save the database.
* @param requestedBufferSize requested buffer size. Actual buffer size may vary.
* @throws IOException if a IO error occurs
*/ */
public DBHandle(int requestBufferSize) throws IOException { public DBHandle(int requestedBufferSize) throws IOException {
this(requestBufferSize, BufferMgr.DEFAULT_CACHE_SIZE); this(requestedBufferSize, BufferMgr.DEFAULT_CACHE_SIZE);
} }
/** /**
* Construct a temporary database handle. * Construct a temporary database handle.
* The saveAs method must be used to save the database. * The saveAs method must be used to save the database.
* @param requestedBufferSize requested buffer size. Actual buffer size may vary.
* @param approxCacheSize approximate size of cache in Bytes.
* @throws IOException if a IO error occurs
*/ */
public DBHandle(int requestBufferSize, long approxCacheSize) throws IOException { public DBHandle(int requestedBufferSize, long approxCacheSize) throws IOException {
bufferMgr = bufferMgr =
new BufferMgr(requestBufferSize, approxCacheSize, BufferMgr.DEFAULT_CHECKPOINT_COUNT); new BufferMgr(requestedBufferSize, approxCacheSize, BufferMgr.DEFAULT_CHECKPOINT_COUNT);
dbParms = new DBParms(bufferMgr, true); dbParms = new DBParms(bufferMgr, true);
dbParms.set(DBParms.MASTER_TABLE_ROOT_BUFFER_ID_PARM, -1); dbParms.set(DBParms.MASTER_TABLE_ROOT_BUFFER_ID_PARM, -1);
masterTable = new MasterTable(this); masterTable = new MasterTable(this);
@ -108,7 +114,7 @@ public class DBHandle {
* @param recover if true an attempt will be made to recover unsaved data if the file is open for update * @param recover if true an attempt will be made to recover unsaved data if the file is open for update
* @param monitor recovery monitor * @param monitor recovery monitor
* @throws IOException if IO error occurs * @throws IOException if IO error occurs
* @throws CancelledException * @throws CancelledException if buffer file recovery is cancelled
*/ */
public DBHandle(BufferFile bufferFile, boolean recover, TaskMonitor monitor) public DBHandle(BufferFile bufferFile, boolean recover, TaskMonitor monitor)
throws IOException, CancelledException { throws IOException, CancelledException {
@ -137,7 +143,7 @@ public class DBHandle {
* for non-update use. This method is provided primarily * for non-update use. This method is provided primarily
* for testing. * for testing.
* @param file buffer file * @param file buffer file
* @throws IOException * @throws IOException if IO error occurs
*/ */
public DBHandle(File file) throws IOException { public DBHandle(File file) throws IOException {
BufferFile bfile = new LocalBufferFile(file, true); BufferFile bfile = new LocalBufferFile(file, true);
@ -159,8 +165,9 @@ public class DBHandle {
/** /**
* Check the consistency of this database. * Check the consistency of this database.
* @param monitor task monitor
* @return true if consistency check passed, else false * @return true if consistency check passed, else false
* @throws CancelledException * @throws CancelledException if consistency check is cancelled
*/ */
public boolean isConsistent(TaskMonitor monitor) throws CancelledException { public boolean isConsistent(TaskMonitor monitor) throws CancelledException {
int consistentCount = 0; int consistentCount = 0;
@ -182,8 +189,9 @@ public class DBHandle {
* Rebuild database tables to resolve certain consistency problems. Use of this * Rebuild database tables to resolve certain consistency problems. Use of this
* method does not recover lost data which may have occurred during original * method does not recover lost data which may have occurred during original
* database corruption. * database corruption.
* @param monitor task monitor
* @return true if rebuild succeeded, else false * @return true if rebuild succeeded, else false
* @throws CancelledException * @throws CancelledException if rebuild is cancelled
*/ */
public boolean rebuild(TaskMonitor monitor) throws CancelledException { public boolean rebuild(TaskMonitor monitor) throws CancelledException {
for (Table table : getTables()) { for (Table table : getTables()) {
@ -205,8 +213,8 @@ public class DBHandle {
* WARNING! Use with extreme caution since this modifies * WARNING! Use with extreme caution since this modifies
* the original file and could destroy data if used * the original file and could destroy data if used
* improperly. * improperly.
* @param file * @param file database buffer file to be updated
* @throws IOException * @throws IOException if IO error occurs
*/ */
public static void resetDatabaseId(File file) throws IOException { public static void resetDatabaseId(File file) throws IOException {
long databaseId = UniversalIdGenerator.nextID().getValue(); long databaseId = UniversalIdGenerator.nextID().getValue();
@ -226,7 +234,7 @@ public class DBHandle {
/** /**
* Read current databaseId * Read current databaseId
* @throws IOException * @throws IOException if IO error occurs
*/ */
private void readDatabaseId() throws IOException { private void readDatabaseId() throws IOException {
try { try {
@ -239,7 +247,7 @@ public class DBHandle {
} }
/** /**
* Returns unique database ID or 0 if this is an older read-only database. * @return unique database ID or 0 if this is an older read-only database.
*/ */
public long getDatabaseId() { public long getDatabaseId() {
return databaseId; return databaseId;
@ -249,7 +257,8 @@ public class DBHandle {
* Returns the recovery changeSet data file for reading or null if one is not available. * Returns the recovery changeSet data file for reading or null if one is not available.
* The caller must dispose of the returned file before peforming generating any new * The caller must dispose of the returned file before peforming generating any new
* recovery snapshots. * recovery snapshots.
* @throws IOException * @return recovery changeSet data file for reading or null if one is not available.
* @throws IOException if IO error occurs
*/ */
public LocalBufferFile getRecoveryChangeSetFile() throws IOException { public LocalBufferFile getRecoveryChangeSetFile() throws IOException {
return bufferMgr.getRecoveryChangeSetFile(); return bufferMgr.getRecoveryChangeSetFile();
@ -262,7 +271,7 @@ public class DBHandle {
* @param monitor task monitor * @param monitor task monitor
* @return true if snapshot successful or not needed, false if an active transaction prevented snapshot * @return true if snapshot successful or not needed, false if an active transaction prevented snapshot
* @throws CancelledException if cancelled by monitor * @throws CancelledException if cancelled by monitor
* @throws IOException * @throws IOException if IO error occurs
*/ */
public boolean takeRecoverySnapshot(DBChangeSet changeSet, TaskMonitor monitor) public boolean takeRecoverySnapshot(DBChangeSet changeSet, TaskMonitor monitor)
throws CancelledException, IOException { throws CancelledException, IOException {
@ -292,7 +301,8 @@ public class DBHandle {
* Returns a shared temporary database handle. * Returns a shared temporary database handle.
* This temporary handle will remain open unitl either this * This temporary handle will remain open unitl either this
* handle is closed or closeScratchPad is invoked. * handle is closed or closeScratchPad is invoked.
* @throws IOException * @return shared temporary database handle.
* @throws IOException if IO error occurs
*/ */
public DBHandle getScratchPad() throws IOException { public DBHandle getScratchPad() throws IOException {
if (scratchPad == null) { if (scratchPad == null) {
@ -314,7 +324,7 @@ public class DBHandle {
/** /**
* Add Database listener * Add Database listener
* @param listener * @param listener database listener
*/ */
public void addListener(DBListener listener) { public void addListener(DBListener listener) {
listenerList.add(listener); listenerList.add(listener);
@ -388,7 +398,7 @@ public class DBHandle {
} }
/** /**
* Returns true if transaction is currently active * @return true if transaction is currently active
*/ */
public boolean isTransactionActive() { public boolean isTransactionActive() {
return txStarted; return txStarted;
@ -414,7 +424,7 @@ public class DBHandle {
* @param commit if true a new checkpoint will be established, if * @param commit if true a new checkpoint will be established, if
* false all changes since the previous checkpoint will be discarded. * false all changes since the previous checkpoint will be discarded.
* @return true if new checkpoint established. * @return true if new checkpoint established.
* @throws IOException * @throws IOException if IO error occurs
*/ */
public synchronized boolean endTransaction(long id, boolean commit) throws IOException { public synchronized boolean endTransaction(long id, boolean commit) throws IOException {
if (id != lastTransactionID) { if (id != lastTransactionID) {
@ -467,7 +477,7 @@ public class DBHandle {
* All upper-levels must clear table-based cached data prior to * All upper-levels must clear table-based cached data prior to
* invoking this method. * invoking this method.
* @return true if an undo was successful * @return true if an undo was successful
* @throws IOException * @throws IOException if IO error occurs
*/ */
public synchronized boolean undo() throws IOException { public synchronized boolean undo() throws IOException {
if (canUndo() && bufferMgr.undo(true)) { if (canUndo() && bufferMgr.undo(true)) {
@ -479,14 +489,14 @@ public class DBHandle {
} }
/** /**
* Returns number of undo-able transactions * @return number of undo-able transactions
*/ */
public int getAvailableUndoCount() { public int getAvailableUndoCount() {
return bufferMgr != null ? bufferMgr.getAvailableUndoCount() : 0; return bufferMgr != null ? bufferMgr.getAvailableUndoCount() : 0;
} }
/** /**
* Returns the number of redo-able transactions * @return the number of redo-able transactions
*/ */
public int getAvailableRedoCount() { public int getAvailableRedoCount() {
return bufferMgr != null ? bufferMgr.getAvailableRedoCount() : 0; return bufferMgr != null ? bufferMgr.getAvailableRedoCount() : 0;
@ -506,7 +516,7 @@ public class DBHandle {
* All upper-levels must clear table-based cached data prior to * All upper-levels must clear table-based cached data prior to
* invoking this method. * invoking this method.
* @return boolean * @return boolean
* @throws IOException * @throws IOException if IO error occurs
*/ */
public synchronized boolean redo() throws IOException { public synchronized boolean redo() throws IOException {
if (canRedo() && bufferMgr.redo()) { if (canRedo() && bufferMgr.redo()) {
@ -565,7 +575,8 @@ public class DBHandle {
/** /**
* Close the database and dispose of the underlying buffer manager. * Close the database and dispose of the underlying buffer manager.
* @param keepRecoveryData * @param keepRecoveryData true if existing recovery data should be retained or false to remove
* any recovery data
*/ */
public synchronized void close(boolean keepRecoveryData) { public synchronized void close(boolean keepRecoveryData) {
closeScratchPad(); closeScratchPad();
@ -577,14 +588,14 @@ public class DBHandle {
} }
/** /**
* Returns true if unsaved changes have been made. * @return true if unsaved changes have been made.
*/ */
public synchronized boolean isChanged() { public synchronized boolean isChanged() {
return bufferMgr != null && bufferMgr.isChanged(); return bufferMgr != null && bufferMgr.isChanged();
} }
/** /**
* Returns true if this database handle has been closed. * @return true if this database handle has been closed.
*/ */
public boolean isClosed() { public boolean isClosed() {
return bufferMgr == null; return bufferMgr == null;
@ -628,7 +639,6 @@ public class DBHandle {
* will be written and set as read-only. The caller is responsbile for disposing the outFile if * will be written and set as read-only. The caller is responsbile for disposing the outFile if
* this parameter is false. * this parameter is false.
* @param monitor progress monitor * @param monitor progress monitor
* @param associateWithNewFile if true this handle will be associated with the new file
* @throws IOException if IO error occurs * @throws IOException if IO error occurs
* @throws CancelledException if monitor cancels operation * @throws CancelledException if monitor cancels operation
*/ */
@ -860,6 +870,8 @@ public class DBHandle {
/** /**
* Returns the Table that was created with the given name or null if * Returns the Table that was created with the given name or null if
* no such table exists. * no such table exists.
* @param name of requested table
* @return table instance or null if not found
*/ */
public Table getTable(String name) { public Table getTable(String name) {
return tables.get(name); return tables.get(name);
@ -896,7 +908,7 @@ public class DBHandle {
* Create secondary indexes as specified by the array of column indexes. * Create secondary indexes as specified by the array of column indexes.
* @param name table name * @param name table name
* @param schema table schema * @param schema table schema
* @param indexedColumns index table columns or null * @param indexedColumns array of column indices which should have an index associated with them
* @return new table instance * @return new table instance
* @throws IOException if IO error occurs during table creation * @throws IOException if IO error occurs during table creation
*/ */
@ -996,6 +1008,7 @@ public class DBHandle {
* buffer size. This value may be used to instatiate a * buffer size. This value may be used to instatiate a
* new BufferFile which is compatible with this database * new BufferFile which is compatible with this database
* when using the saveAs method. * when using the saveAs method.
* @return buffer size utilized by this database
*/ */
public int getBufferSize() { public int getBufferSize() {
return bufferMgr.getBufferSize(); return bufferMgr.getBufferSize();

View file

@ -24,7 +24,7 @@ import java.util.List;
* in the current tree view (collapsed). Of course, that decision would need to be balanced * in the current tree view (collapsed). Of course, that decision would need to be balanced
* against the extra time to reload the nodes in the event that a filter is applied. Also, if * against the extra time to reload the nodes in the event that a filter is applied. Also, if
* some external event occurs that changes the set of children for a GTreeLazyNode, you can call * some external event occurs that changes the set of children for a GTreeLazyNode, you can call
* {@link #reload()} to refresh the node's children. * {@link #unloadChildren()} to clear any previously loaded children.
*/ */
public abstract class GTreeLazyNode extends GTreeNode { public abstract class GTreeLazyNode extends GTreeNode {

View file

@ -46,7 +46,7 @@ public class RestrictedValueSortedMap<K, V> implements ValueSortedMap<K, V> {
/** /**
* Construct an iterator starting at a given index of the <em>sub</em> list. * Construct an iterator starting at a given index of the <em>sub</em> list.
* *
* @param start * @param start initial iterator position
*/ */
public RestrictedEntryListIterator(int start) { public RestrictedEntryListIterator(int start) {
this.wit = wrapped.entrySet().listIterator(getLowestIndex() + start); this.wit = wrapped.entrySet().listIterator(getLowestIndex() + start);
@ -125,7 +125,7 @@ public class RestrictedValueSortedMap<K, V> implements ValueSortedMap<K, V> {
/** /**
* Construct an iterator starting at a given index of the <em>sub</em> list. * Construct an iterator starting at a given index of the <em>sub</em> list.
* *
* @param start * @param start initial iterator position
*/ */
public RestrictedKeyListIterator(int start) { public RestrictedKeyListIterator(int start) {
this.wit = new RestrictedEntryListIterator(start); this.wit = new RestrictedEntryListIterator(start);
@ -186,8 +186,6 @@ public class RestrictedValueSortedMap<K, V> implements ValueSortedMap<K, V> {
/** /**
* Construct an iterator * Construct an iterator
*
* @param start
*/ */
public RestrictedValueListIterator() { public RestrictedValueListIterator() {
this(0); this(0);
@ -196,7 +194,7 @@ public class RestrictedValueSortedMap<K, V> implements ValueSortedMap<K, V> {
/** /**
* Construct an iterator starting at a given index of the <em>sub</em> list. * Construct an iterator starting at a given index of the <em>sub</em> list.
* *
* @param start * @param start initial iterator position
*/ */
public RestrictedValueListIterator(int start) { public RestrictedValueListIterator(int start) {
this.wit = new RestrictedEntryListIterator(start); this.wit = new RestrictedEntryListIterator(start);

View file

@ -24,8 +24,8 @@ import java.util.*;
* This is an extension of {@link Map} where entries are sorted by value, rather than by key. Such a * This is an extension of {@link Map} where entries are sorted by value, rather than by key. Such a
* map may be useful as a priority queue where the cost of an entry may change over time. As such, * map may be useful as a priority queue where the cost of an entry may change over time. As such,
* the collections returned by {@link #entrySet()}, {@link #keySet()}, and {@link #values()} all * the collections returned by {@link #entrySet()}, {@link #keySet()}, and {@link #values()} all
* extend {@link Deque}. The order of the entries will be updated on any call to {@link #put(Object, * extend {@link Deque}. The order of the entries will be updated on any call to {@link Map#put(Object, Object)},
* Object))}, or a call to {@link Collection#add(Object)} on the entry set. Additionally, if the * or a call to {@link Collection#add(Object)} on the entry set. Additionally, if the
* values are mutable objects, whose order may change, there is an {@link #update(Object)} method, * values are mutable objects, whose order may change, there is an {@link #update(Object)} method,
* which notifies the map that the given key may need to be repositioned. The associated collections * which notifies the map that the given key may need to be repositioned. The associated collections
* also extend the {@link List} interface, providing fairly efficient implementations of * also extend the {@link List} interface, providing fairly efficient implementations of

View file

@ -39,7 +39,7 @@ import sun.security.x509.*;
* suffice. * suffice.
* <p> * <p>
* <b>NOTE:</b> This class makes direct use of classes within the * <b>NOTE:</b> This class makes direct use of classes within the
* {@link sun.security.x509} package thus breaking portability. While this is * <code>sun.security.x509</code> package thus breaking portability. While this is
* not preferred, the ability to generate X.509 certificates and keystores * not preferred, the ability to generate X.509 certificates and keystores
* appears to be absent from the standard java/javax packages. * appears to be absent from the standard java/javax packages.
*/ */

View file

@ -31,7 +31,7 @@ public class LittleEndianDataConverter implements DataConverter {
/** /**
* Don't use this constructor to create new instances of this class. Use the static {@link #INSTANCE} instead * Don't use this constructor to create new instances of this class. Use the static {@link #INSTANCE} instead
* or {@link DataConverter#getInstance(Endian)} * or {@link DataConverter#getInstance(boolean)}
*/ */
public LittleEndianDataConverter() { public LittleEndianDataConverter() {
// empty // empty

View file

@ -71,7 +71,6 @@ public class FVSlider extends JSlider
* @param scrollPane * @param scrollPane
* @param table * @param table
* @param viewportUtility * @param viewportUtility
* @param eventListener
* @param model * @param model
* @param reader * @param reader
* @param eventListener * @param eventListener

View file

@ -51,27 +51,27 @@ public interface AddressSetView extends Iterable<AddressRange> {
public boolean contains(AddressSetView rangeSet); public boolean contains(AddressSetView rangeSet);
/** /**
* Returns true if this set is empty. * @return true if this set is empty.
*/ */
public boolean isEmpty(); public boolean isEmpty();
/** /**
* Return the minimum address for this set. Returns null if the set is empty. * @return the minimum address for this set. Returns null if the set is empty.
*/ */
public Address getMinAddress(); public Address getMinAddress();
/** /**
* Return the maximum address for this set. Returns null if the set is empty. * @return the maximum address for this set. Returns null if the set is empty.
*/ */
public Address getMaxAddress(); public Address getMaxAddress();
/** /**
* Return the number of address ranges in this set. * @return the number of address ranges in this set.
*/ */
public int getNumAddressRanges(); public int getNumAddressRanges();
/** /**
* Returns an iterator over the address ranges in this address set. * @return an iterator over the address ranges in this address set.
*/ */
public AddressRangeIterator getAddressRanges(); public AddressRangeIterator getAddressRanges();
@ -120,7 +120,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
public Iterator<AddressRange> iterator(Address start, boolean forward); public Iterator<AddressRange> iterator(Address start, boolean forward);
/** /**
* Returns the number of addresses in this set. * @return the number of addresses in this set.
*/ */
public long getNumAddresses(); public long getNumAddresses();
@ -128,6 +128,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
* Returns an iterator over all addresses in this set. * Returns an iterator over all addresses in this set.
* @param forward if true the address are return in increasing order, otherwise in * @param forward if true the address are return in increasing order, otherwise in
* decreasing order. * decreasing order.
* @return an iterator over all addresses in this set.
*/ */
public AddressIterator getAddresses(boolean forward); public AddressIterator getAddresses(boolean forward);
@ -136,6 +137,8 @@ public interface AddressSetView extends Iterable<AddressRange> {
* starting at the start address * starting at the start address
* @param start address to start iterating at in the address set * @param start address to start iterating at in the address set
* @param forward if true address are return from lowest to highest, else from highest to lowest * @param forward if true address are return from lowest to highest, else from highest to lowest
* @return an iterator over the addresses in this address set
* starting at the start address
*/ */
public AddressIterator getAddresses(Address start, boolean forward); public AddressIterator getAddresses(Address start, boolean forward);
@ -143,6 +146,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
* Determine if this address set intersects with the specified address set. * Determine if this address set intersects with the specified address set.
* *
* @param addrSet address set to check intersection with. * @param addrSet address set to check intersection with.
* @return true if this set intersects the specified addrSet else false
*/ */
public boolean intersects(AddressSetView addrSet); public boolean intersects(AddressSetView addrSet);
@ -196,7 +200,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
/** /**
* Computes the exclusive-or of this address set with the given set. This * Computes the exclusive-or of this address set with the given set. This
* method does not modify this address set. * method does not modify this address set.
* @param addrSet * @param addrSet address set to exclusive-or with.
* @return AddressSet a new address set containing all addresses that are in * @return AddressSet a new address set containing all addresses that are in
* either this set or the given set, but not in both sets * either this set or the given set, but not in both sets
*/ */

View file

@ -30,7 +30,7 @@ import ghidra.util.GhidraDataConverter;
* the overhead of various error checks. This implementation will not wrap * the overhead of various error checks. This implementation will not wrap
* if the end of the memory space is encountered. * if the end of the memory space is encountered.
* *
* The {@link #getByte(int), #getBytes(byte[], int)} methods can cause the bytes in the * The {@link #getByte(int)}, {@link #getBytes(byte[], int)} methods can cause the bytes in the
* buffer cache if the request is outside of the current cached bytes. * buffer cache if the request is outside of the current cached bytes.
* *
* WARNING: The underlying MemBuffer should not change its base address. Using a * WARNING: The underlying MemBuffer should not change its base address. Using a
@ -67,7 +67,7 @@ public class WrappedMemBuffer implements MemBuffer {
/** /**
* Construct a wrapped MemBuffer with an adjustable base offset * Construct a wrapped MemBuffer with an adjustable base offset
* @param buf memory buffer * @param buf memory buffer
* @buffersize size of cache buffer - specify 0 for no buffering * @param bufferSize size of cache buffer - specify 0 for no buffering
* @param baseOffset offset relative to the underlying buffer's start address * @param baseOffset offset relative to the underlying buffer's start address
* (addr + baseOffset) will be the 0 index into this buffer * (addr + baseOffset) will be the 0 index into this buffer
* @throws AddressOutOfBoundsException * @throws AddressOutOfBoundsException
@ -113,10 +113,12 @@ public class WrappedMemBuffer implements MemBuffer {
private int computeOffset(int offset) throws MemoryAccessException { private int computeOffset(int offset) throws MemoryAccessException {
int bufOffset = baseOffset + offset; int bufOffset = baseOffset + offset;
if (offset > 0 && bufOffset < baseOffset) { if (offset > 0 && bufOffset < baseOffset) {
throw new MemoryAccessException("Invalid WrappedMemBuffer, offset would wrap underlying memory buffer"); throw new MemoryAccessException(
"Invalid WrappedMemBuffer, offset would wrap underlying memory buffer");
} }
if (offset < 0 && bufOffset > baseOffset) { if (offset < 0 && bufOffset > baseOffset) {
throw new MemoryAccessException("Invalid WrappedMemBuffer offset, offset would wrap underlying memory buffer"); throw new MemoryAccessException(
"Invalid WrappedMemBuffer offset, offset would wrap underlying memory buffer");
} }
return bufOffset; return bufOffset;
} }
@ -157,7 +159,8 @@ public class WrappedMemBuffer implements MemBuffer {
// grab from wrapped buffer, too many bytes, or no buffer // grab from wrapped buffer, too many bytes, or no buffer
return memBuffer.getBytes(b, computeOffset(offset)); return memBuffer.getBytes(b, computeOffset(offset));
} catch (MemoryAccessException e) { }
catch (MemoryAccessException e) {
return 0; return 0;
} }
} }
@ -186,22 +189,22 @@ public class WrappedMemBuffer implements MemBuffer {
@Override @Override
public short getShort(int offset) throws MemoryAccessException { public short getShort(int offset) throws MemoryAccessException {
return converter.getShort(this, computeOffset(offset)); return converter.getShort(this, offset);
} }
@Override @Override
public int getInt(int offset) throws MemoryAccessException { public int getInt(int offset) throws MemoryAccessException {
return converter.getInt(this, computeOffset(offset)); return converter.getInt(this, offset);
} }
@Override @Override
public long getLong(int offset) throws MemoryAccessException { public long getLong(int offset) throws MemoryAccessException {
return converter.getLong(this, computeOffset(offset)); return converter.getLong(this, offset);
} }
@Override @Override
public BigInteger getBigInteger(int offset, int size, boolean signed) public BigInteger getBigInteger(int offset, int size, boolean signed)
throws MemoryAccessException { throws MemoryAccessException {
return converter.getBigInteger(this, computeOffset(offset), size, signed); return converter.getBigInteger(this, offset, size, signed);
} }
} }

View file

@ -718,7 +718,7 @@ define pcodeop coproc_moveto_Security_world_control;
define pcodeop coproc_moveto_Translation_table; define pcodeop coproc_moveto_Translation_table;
define pcodeop coproc_moveto_Instruction_cache; define pcodeop coproc_moveto_Instruction_cache;
define pcodeop coproc_moveto_Data_cache_operations; define pcodeop coproc_moveto_Data_cache_operations;
define pcodeop coproc_moveto_Idetification_registers; define pcodeop coproc_moveto_Identification_registers;
define pcodeop coproc_moveto_Peripheral_System; define pcodeop coproc_moveto_Peripheral_System;
define pcodeop coproc_movefrom_Main_ID; define pcodeop coproc_movefrom_Main_ID;
@ -768,7 +768,7 @@ define pcodeop coproc_movefrom_Security_world_control;
define pcodeop coproc_movefrom_Translation_table; define pcodeop coproc_movefrom_Translation_table;
define pcodeop coproc_movefrom_Instruction_cache; define pcodeop coproc_movefrom_Instruction_cache;
define pcodeop coproc_movefrom_Data_cache_operations; define pcodeop coproc_movefrom_Data_cache_operations;
define pcodeop coproc_movefrom_Idetification_registers; define pcodeop coproc_movefrom_Identification_registers;
define pcodeop coproc_movefrom_Peripheral_System; define pcodeop coproc_movefrom_Peripheral_System;
mcrOperands: cpn,opc1,Rd,CRn,CRm,opc2 is CRm & opc2 & cpn & CRn & opc1 & Rd { } mcrOperands: cpn,opc1,Rd,CRn,CRm,opc2 is CRm & opc2 & cpn & CRn & opc1 & Rd { }
@ -3323,7 +3323,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
{ {
build COND; build COND;
t_opc2:4 = opc2; t_crm:4 = CRm; t_opc2:4 = opc2; t_crm:4 = CRm;
coproc_moveto_Idetification_registers(Rd,t_opc2,t_crm); coproc_moveto_Identification_registers(Rd,t_opc2,t_crm);
} }
@ -4013,7 +4013,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
{ {
build COND; build COND;
t_opc2:4 = opc2; t_crm:4 = CRm; t_opc2:4 = opc2; t_crm:4 = CRm;
Rd = coproc_movefrom_Idetification_registers(t_opc2,t_crm); Rd = coproc_movefrom_Identification_registers(t_opc2,t_crm);
} }