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
*/

View file

@ -157,7 +157,7 @@ public interface ElfConstants {
/**No machine*/
public static final short EM_NONE = 0;
/** AT&T WE 32100 */
/** AT&T WE 32100 */
public static final short EM_M32 = 1;
/**SUN SPARC */
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
*/
abstract protected String getTypeString();

View file

@ -187,12 +187,12 @@ public class Pattern extends DittedBitSequence {
/**
* Read just the post patterns from the <patternpair> tags
* @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
* @throws IOException
* @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 {
ErrorHandler handler = new ErrorHandler() {
@Override
@ -217,7 +217,7 @@ public class Pattern extends DittedBitSequence {
if (el.getName().equals("patternpairs")) {
PatternPairSet pairset = new PatternPairSet();
pairset.restoreXml(parser, pfactory);
pairset.extractPostPatterns(patlist);
pairset.extractPostPatterns(patternList);
}
else {
parser.next();

View file

@ -87,30 +87,31 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
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 });
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 WrappedMemBuffer(memBuf, 4, 0);
byte[] bytes = new byte[6];
// test get too many for cache
assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
// test not in buffer
memBuf = new WrappedMemBuffer(memBuf, 6, 0);
assertEquals(6, memBuf.getBytes(bytes, 0));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 0, 1, 2, 3, 4, 5 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 0, 1, 2, 3, 4, 5 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 8));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 8, 9, 10, 11, 12, 13 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 8, 9, 10, 11, 12, 13 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 1));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 1, 2, 3, 4, 5, 6 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 1, 2, 3, 4, 5, 6 }, bytes);
assertEquals(10, memBuf.getByte(10));
assertEquals(0, memBuf.getByte(0));
@ -124,30 +125,31 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
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 });
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 WrappedMemBuffer(memBuf, 0, 0);
byte[] bytes = new byte[6];
// test get too many for cache
assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
// test not in buffer
memBuf = new WrappedMemBuffer(memBuf, 0, 0);
assertEquals(6, memBuf.getBytes(bytes, 0));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 0, 1, 2, 3, 4, 5 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 0, 1, 2, 3, 4, 5 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 2));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 2, 3, 4, 5, 6, 7 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 2, 3, 4, 5, 6, 7 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 8));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 8, 9, 10, 11, 12, 13 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 8, 9, 10, 11, 12, 13 }, bytes);
assertEquals(6, memBuf.getBytes(bytes, 1));
Assert.assertArrayEquals("Unexpected bytes read from memBuf", new byte[] { 1, 2, 3, 4, 5, 6 },
bytes);
Assert.assertArrayEquals("Unexpected bytes read from memBuf",
new byte[] { 1, 2, 3, 4, 5, 6 }, bytes);
assertEquals(10, memBuf.getByte(10));
assertEquals(0, memBuf.getByte(0));
@ -155,6 +157,151 @@ public class WrappedMemoryBufferTest extends AbstractGhidraHeadedIntegrationTest
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 {
Memory mem = program.getMemory();

View file

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

View file

@ -530,6 +530,25 @@ public class TypeParser {
type = new UserDefinedTypeModuleSourceAndLineMsType(pdb, reader);
//TODO: more work
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:
// This should never happen (unless we missed something
// or MSFT has added new in a version we do not handle.

View file

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

View file

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

View file

@ -72,8 +72,10 @@ public abstract class AbstractEnumMsType extends AbstractComplexMsType {
myBuilder.append(" ");
myBuilder.append(name);
myBuilder.append("<");
if (count != -1) {
myBuilder.append(count);
myBuilder.append(",");
}
myBuilder.append(pdb.getTypeRecord(underlyingRecordNumber));
myBuilder.append(",");
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();
if (argDataType == null) {
String message =
applicator.appendLogMsg(
"PDB Warning: No type conversion for " + argApplier.getMsType().toString() +
" for parameter " + parameterCount + " of " + functionDefinition.getName();
applicator.appendLogMsg(message);
" for parameter " + parameterCount + " of " + functionDefinition.getName());
}
else {
try {
ParameterDefinition parameterDefinition =
new ParameterDefinitionImpl(null, argDataType, "");
parameterDefinitionList.add(parameterDefinition);
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(
new ParameterDefinition[parameterDefinitionList.size()]));

View file

@ -309,7 +309,8 @@ public class FunctionSymbolApplier extends MsSymbolApplier {
new ApplyFunctionSignatureCmd(address, def, SourceType.IMPORTED);
if (!sigCmd.applyTo(applicator.getProgram(), monitor)) {
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;
}
}

View file

@ -552,8 +552,7 @@ public class PdbApplicator {
int num = pdb.getDebugInfo().getNumModules();
for (int index = 1; index <= num; index++) {
monitor.checkCanceled();
String moduleName =
pdb.getDebugInfo().getModuleInformation(index).getModuleName();
String moduleName = pdb.getDebugInfo().getModuleInformation(index).getModuleName();
categoryNames.add(moduleName);
}
@ -1266,7 +1265,9 @@ public class PdbApplicator {
NamespaceUtils.getNonFunctionNamespace(program, path.getParent());
if (parentNamespace == null) {
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;
}
defineNamespace(parentNamespace, path.getName(), isClass);
@ -1294,7 +1295,8 @@ public class PdbApplicator {
else if (namespace.getSymbol().getSymbolType() == SymbolType.NAMESPACE) {
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));
}
else if (isClass) {
@ -1305,8 +1307,9 @@ public class PdbApplicator {
}
}
catch (InvalidInputException | DuplicateNameException e) {
log.appendMsg("Unable to create class namespace: " + parentNamespace.getName(true) +
Namespace.DELIMITER + name + " due to exception: " + e.toString());
log.appendMsg(
"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;
}
catch (InvalidInputException e) {
log.appendMsg("Unable to create symbol: " + e.getMessage());
log.appendMsg("PDB Warning: Unable to create symbol: " + e.getMessage());
}
return false;
}
@ -1532,7 +1535,8 @@ public class PdbApplicator {
namespace, name, SourceType.IMPORTED);
}
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;
}

View file

@ -93,11 +93,13 @@ public class PointerTypeApplier extends MsTypeApplier {
if (underlyingType == null) {
// TODO: we have seen underlyingTypeApplier is for NoTypeApplier for VtShapeMsType
// Figure it out, and perhaps create an applier that creates a structure or something?
return new VoidDataType(applicator.getDataTypeManager());
// throw new PdbException("Underlying type missing for pointer.");
underlyingType = applicator.getPdbPrimitiveTypeApplicator().getVoidType();
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()) {
size = -1; // Use default
}

View file

@ -494,6 +494,29 @@ public class TypeApplierFactory {
case UserDefinedTypeModuleSourceAndLineMsType.PDB_ID:
applier = new UdtSourceLineTypeApplier(applicator, type);
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
// 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);
}
//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
public void testStructure16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
@ -463,6 +486,29 @@ public class TypesTest extends AbstractGenericTest {
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
public void testInterfaceMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
@ -484,15 +530,38 @@ public class TypesTest extends AbstractGenericTest {
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
public void testUnion16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
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.
byte[] propertyBuffer = createMsPropertyBuffer();
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.putPadding(2);
PdbByteReader reader = new PdbByteReader(writer.get());
@ -506,11 +575,11 @@ public class TypesTest extends AbstractGenericTest {
public void testUnionStMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
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();
writer.putBytes(propertyBuffer);
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("OtherNameSt");
writer.putAlign(2);
@ -525,11 +594,11 @@ public class TypesTest extends AbstractGenericTest {
public void testUnionMsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
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();
writer.putBytes(propertyBuffer);
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("OtherName");
writer.putAlign(2);
@ -540,6 +609,27 @@ public class TypesTest extends AbstractGenericTest {
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
public void testEnum16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();
@ -596,6 +686,26 @@ public class TypesTest extends AbstractGenericTest {
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
public void testProcedure16MsType() throws Exception {
PdbByteWriter writer = new PdbByteWriter();

View file

@ -54,6 +54,7 @@ public class DBHandle {
/**
* Construct a temporary database handle.
* The saveAs method must be used to save the database.
* @throws IOException if a IO error occurs
*/
public DBHandle() throws IOException {
this(BufferMgr.DEFAULT_BUFFER_SIZE, BufferMgr.DEFAULT_CACHE_SIZE);
@ -62,18 +63,23 @@ public class DBHandle {
/**
* Construct a temporary database handle.
* 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 {
this(requestBufferSize, BufferMgr.DEFAULT_CACHE_SIZE);
public DBHandle(int requestedBufferSize) throws IOException {
this(requestedBufferSize, BufferMgr.DEFAULT_CACHE_SIZE);
}
/**
* Construct a temporary database handle.
* 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 =
new BufferMgr(requestBufferSize, approxCacheSize, BufferMgr.DEFAULT_CHECKPOINT_COUNT);
new BufferMgr(requestedBufferSize, approxCacheSize, BufferMgr.DEFAULT_CHECKPOINT_COUNT);
dbParms = new DBParms(bufferMgr, true);
dbParms.set(DBParms.MASTER_TABLE_ROOT_BUFFER_ID_PARM, -1);
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 monitor recovery monitor
* @throws IOException if IO error occurs
* @throws CancelledException
* @throws CancelledException if buffer file recovery is cancelled
*/
public DBHandle(BufferFile bufferFile, boolean recover, TaskMonitor monitor)
throws IOException, CancelledException {
@ -137,7 +143,7 @@ public class DBHandle {
* for non-update use. This method is provided primarily
* for testing.
* @param file buffer file
* @throws IOException
* @throws IOException if IO error occurs
*/
public DBHandle(File file) throws IOException {
BufferFile bfile = new LocalBufferFile(file, true);
@ -159,8 +165,9 @@ public class DBHandle {
/**
* Check the consistency of this database.
* @param monitor task monitor
* @return true if consistency check passed, else false
* @throws CancelledException
* @throws CancelledException if consistency check is cancelled
*/
public boolean isConsistent(TaskMonitor monitor) throws CancelledException {
int consistentCount = 0;
@ -182,8 +189,9 @@ public class DBHandle {
* Rebuild database tables to resolve certain consistency problems. Use of this
* method does not recover lost data which may have occurred during original
* database corruption.
* @param monitor task monitor
* @return true if rebuild succeeded, else false
* @throws CancelledException
* @throws CancelledException if rebuild is cancelled
*/
public boolean rebuild(TaskMonitor monitor) throws CancelledException {
for (Table table : getTables()) {
@ -205,8 +213,8 @@ public class DBHandle {
* WARNING! Use with extreme caution since this modifies
* the original file and could destroy data if used
* improperly.
* @param file
* @throws IOException
* @param file database buffer file to be updated
* @throws IOException if IO error occurs
*/
public static void resetDatabaseId(File file) throws IOException {
long databaseId = UniversalIdGenerator.nextID().getValue();
@ -226,7 +234,7 @@ public class DBHandle {
/**
* Read current databaseId
* @throws IOException
* @throws IOException if IO error occurs
*/
private void readDatabaseId() throws IOException {
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() {
return databaseId;
@ -249,7 +257,8 @@ public class DBHandle {
* 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
* 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 {
return bufferMgr.getRecoveryChangeSetFile();
@ -262,7 +271,7 @@ public class DBHandle {
* @param monitor task monitor
* @return true if snapshot successful or not needed, false if an active transaction prevented snapshot
* @throws CancelledException if cancelled by monitor
* @throws IOException
* @throws IOException if IO error occurs
*/
public boolean takeRecoverySnapshot(DBChangeSet changeSet, TaskMonitor monitor)
throws CancelledException, IOException {
@ -292,7 +301,8 @@ public class DBHandle {
* Returns a shared temporary database handle.
* This temporary handle will remain open unitl either this
* 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 {
if (scratchPad == null) {
@ -314,7 +324,7 @@ public class DBHandle {
/**
* Add Database listener
* @param listener
* @param listener database listener
*/
public void addListener(DBListener 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() {
return txStarted;
@ -414,7 +424,7 @@ public class DBHandle {
* @param commit if true a new checkpoint will be established, if
* false all changes since the previous checkpoint will be discarded.
* @return true if new checkpoint established.
* @throws IOException
* @throws IOException if IO error occurs
*/
public synchronized boolean endTransaction(long id, boolean commit) throws IOException {
if (id != lastTransactionID) {
@ -467,7 +477,7 @@ public class DBHandle {
* All upper-levels must clear table-based cached data prior to
* invoking this method.
* @return true if an undo was successful
* @throws IOException
* @throws IOException if IO error occurs
*/
public synchronized boolean undo() throws IOException {
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() {
return bufferMgr != null ? bufferMgr.getAvailableUndoCount() : 0;
}
/**
* Returns the number of redo-able transactions
* @return the number of redo-able transactions
*/
public int getAvailableRedoCount() {
return bufferMgr != null ? bufferMgr.getAvailableRedoCount() : 0;
@ -506,7 +516,7 @@ public class DBHandle {
* All upper-levels must clear table-based cached data prior to
* invoking this method.
* @return boolean
* @throws IOException
* @throws IOException if IO error occurs
*/
public synchronized boolean redo() throws IOException {
if (canRedo() && bufferMgr.redo()) {
@ -565,7 +575,8 @@ public class DBHandle {
/**
* 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) {
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() {
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() {
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
* this parameter is false.
* @param monitor progress monitor
* @param associateWithNewFile if true this handle will be associated with the new file
* @throws IOException if IO error occurs
* @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
* no such table exists.
* @param name of requested table
* @return table instance or null if not found
*/
public Table getTable(String name) {
return tables.get(name);
@ -896,7 +908,7 @@ public class DBHandle {
* Create secondary indexes as specified by the array of column indexes.
* @param name table name
* @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
* @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
* new BufferFile which is compatible with this database
* when using the saveAs method.
* @return buffer size utilized by this database
*/
public int 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
* 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
* {@link #reload()} to refresh the node's children.
* {@link #unloadChildren()} to clear any previously loaded children.
*/
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.
*
* @param start
* @param start initial iterator position
*/
public RestrictedEntryListIterator(int 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.
*
* @param start
* @param start initial iterator position
*/
public RestrictedKeyListIterator(int start) {
this.wit = new RestrictedEntryListIterator(start);
@ -186,8 +186,6 @@ public class RestrictedValueSortedMap<K, V> implements ValueSortedMap<K, V> {
/**
* Construct an iterator
*
* @param start
*/
public RestrictedValueListIterator() {
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.
*
* @param start
* @param start initial iterator position
*/
public RestrictedValueListIterator(int 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
* 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
* extend {@link Deque}. The order of the entries will be updated on any call to {@link #put(Object,
* Object))}, or a call to {@link Collection#add(Object)} on the entry set. Additionally, if the
* extend {@link Deque}. The order of the entries will be updated on any call to {@link Map#put(Object, Object)},
* 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,
* 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

View file

@ -39,7 +39,7 @@ import sun.security.x509.*;
* suffice.
* <p>
* <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
* 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
* or {@link DataConverter#getInstance(Endian)}
* or {@link DataConverter#getInstance(boolean)}
*/
public LittleEndianDataConverter() {
// empty

View file

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

View file

@ -51,27 +51,27 @@ public interface AddressSetView extends Iterable<AddressRange> {
public boolean contains(AddressSetView rangeSet);
/**
* Returns true if this set is empty.
* @return true if this set is empty.
*/
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();
/**
* 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();
/**
* Return the number of address ranges in this set.
* @return the number of address ranges in this set.
*/
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();
@ -120,7 +120,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
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();
@ -128,6 +128,7 @@ public interface AddressSetView extends Iterable<AddressRange> {
* Returns an iterator over all addresses in this set.
* @param forward if true the address are return in increasing order, otherwise in
* decreasing order.
* @return an iterator over all addresses in this set.
*/
public AddressIterator getAddresses(boolean forward);
@ -136,6 +137,8 @@ public interface AddressSetView extends Iterable<AddressRange> {
* starting at the start address
* @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
* @return an iterator over the addresses in this address set
* starting at the start address
*/
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.
*
* @param addrSet address set to check intersection with.
* @return true if this set intersects the specified addrSet else false
*/
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
* 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
* 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
* 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.
*
* 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
* @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
* (addr + baseOffset) will be the 0 index into this buffer
* @throws AddressOutOfBoundsException
@ -113,10 +113,12 @@ public class WrappedMemBuffer implements MemBuffer {
private int computeOffset(int offset) throws MemoryAccessException {
int bufOffset = baseOffset + offset;
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) {
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;
}
@ -157,7 +159,8 @@ public class WrappedMemBuffer implements MemBuffer {
// grab from wrapped buffer, too many bytes, or no buffer
return memBuffer.getBytes(b, computeOffset(offset));
} catch (MemoryAccessException e) {
}
catch (MemoryAccessException e) {
return 0;
}
}
@ -186,22 +189,22 @@ public class WrappedMemBuffer implements MemBuffer {
@Override
public short getShort(int offset) throws MemoryAccessException {
return converter.getShort(this, computeOffset(offset));
return converter.getShort(this, offset);
}
@Override
public int getInt(int offset) throws MemoryAccessException {
return converter.getInt(this, computeOffset(offset));
return converter.getInt(this, offset);
}
@Override
public long getLong(int offset) throws MemoryAccessException {
return converter.getLong(this, computeOffset(offset));
return converter.getLong(this, offset);
}
@Override
public BigInteger getBigInteger(int offset, int size, boolean signed)
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_Instruction_cache;
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_movefrom_Main_ID;
@ -768,7 +768,7 @@ define pcodeop coproc_movefrom_Security_world_control;
define pcodeop coproc_movefrom_Translation_table;
define pcodeop coproc_movefrom_Instruction_cache;
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;
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;
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;
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);
}