GP-4383 - PDB - Changes to MultiphaseResolver and IOException propagation; extract ClassFieldAttributes from CppCompositeType

This commit is contained in:
ghizard 2024-03-12 11:27:13 -04:00
parent ddfb041885
commit 0d68aab0a8
12 changed files with 508 additions and 374 deletions

View File

@ -80,14 +80,11 @@ public class DebugData {
/**
* Returns the Frame Pointer Omission data
* @return the framePointerOmissionData or null if does not exist
* @throws PdbException PdbException upon error in processing components
* @return the framePointerOmissionData or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public List<FramePointerOmissionRecord> getFramePointerOmissionData()
throws CancelledException, PdbException, IOException {
throws CancelledException {
int streamNum = debugStreams.get(DebugType.FRAME_POINTER_OMISSION.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -105,14 +102,10 @@ public class DebugData {
/**
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
* @return the omapFromSource or null if does not exist.
* @throws PdbException PdbException upon error in processing components
* @return the omapFromSource or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public SortedMap<Long, Long> getOmapFromSource()
throws CancelledException, PdbException, IOException {
public SortedMap<Long, Long> getOmapFromSource() throws CancelledException {
int streamNum = debugStreams.get(DebugType.OMAP_FROM_SOURCE.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -122,14 +115,10 @@ public class DebugData {
/**
* Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;
* @return the imageSectionHeaders or null if does not exist
* @throws PdbException PdbException upon error in processing components
* @return the imageSectionHeaders or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public List<ImageSectionHeader> getImageSectionHeaders()
throws CancelledException, PdbException, IOException {
public List<ImageSectionHeader> getImageSectionHeaders() throws CancelledException {
int streamNum = debugStreams.get(DebugType.SECTION_HEADER.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -141,15 +130,11 @@ public class DebugData {
* Returns XData
* When this returns a non-null list the OMAP_FROM_SRC should be
* used for remapping global symbols
* @return the imageSectionHeadersOrig or null if does not exist
* @throws PdbException PdbException upon error in processing components
* @return the imageSectionHeadersOrig or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
// TODO: just put a return of null Integer for now until figured out.
public Integer getXData()
throws CancelledException, PdbException, IOException {
public Integer getXData() throws CancelledException {
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -161,14 +146,10 @@ public class DebugData {
* Returns PData
* When this returns a non-null list the OMAP_FROM_SRC should be
* used for remapping global symbols
* @return the imageSectionHeadersOrig or null if does not exist
* @throws PdbException PdbException upon error in processing components
* @return the imageSectionHeadersOrig or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public List<ImageFunctionEntry> getPData()
throws CancelledException, PdbException, IOException {
public List<ImageFunctionEntry> getPData() throws CancelledException {
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -180,14 +161,10 @@ public class DebugData {
* Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;.
* When this returns a non-null list the OMAP_FROM_SRC should be
* used for remapping global symbols
* @return the imageSectionHeadersOrig or null if does not exist
* @throws PdbException PdbException upon error in processing components
* @return the imageSectionHeadersOrig or null if does not exist or problem parsing
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public List<ImageSectionHeader> getImageSectionHeadersOrig()
throws CancelledException, PdbException, IOException {
public List<ImageSectionHeader> getImageSectionHeadersOrig() throws CancelledException {
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
return null;
@ -208,8 +185,7 @@ public class DebugData {
* @throws PdbException upon error in processing components
* @throws CancelledException upon user cancellation
*/
public void deserializeHeader(PdbByteReader reader)
throws PdbException, CancelledException {
public void deserializeHeader(PdbByteReader reader) throws PdbException, CancelledException {
while (reader.hasMore()) {
pdb.checkCancelled();
int debugStreamNumber = reader.parseUnsignedShortVal();
@ -230,8 +206,7 @@ public class DebugData {
* inability to read required bytes
*/
@Deprecated
public void deserialize()
throws PdbException, CancelledException, IOException {
public void deserialize() throws PdbException, CancelledException, IOException {
if (debugStreams.isEmpty()) {
throw new PdbException(
"DebugData Header had not been deserialized at the appropriate time");
@ -281,44 +256,67 @@ public class DebugData {
}
private List<FramePointerOmissionRecord> deserializeFramePointerOmissionData(int streamNum)
throws PdbException, CancelledException, IOException {
throws CancelledException {
// TODO: check implementation for completeness.
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<FramePointerOmissionRecord> fpOmissionData = new ArrayList<>();
while (reader.hasMore()) {
pdb.checkCancelled();
FramePointerOmissionRecord framePointerOmissionRecord =
new FramePointerOmissionRecord();
framePointerOmissionRecord.parse(reader);
fpOmissionData.add(framePointerOmissionRecord);
try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<FramePointerOmissionRecord> fpOmissionData = new ArrayList<>();
while (reader.hasMore()) {
pdb.checkCancelled();
FramePointerOmissionRecord framePointerOmissionRecord =
new FramePointerOmissionRecord();
framePointerOmissionRecord.parse(reader);
fpOmissionData.add(framePointerOmissionRecord);
}
return fpOmissionData;
}
return fpOmissionData;
catch (PdbException | IOException e) {
PdbLog.message("Returning null Debug Frame Pointer Omission Data due to" +
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
return null;
}
}
private SortedMap<Long, Long> deserializeOMap(int streamNum)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
SortedMap<Long, Long> omap = new TreeMap<>();
while (reader.hasMore()) {
pdb.checkCancelled();
long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal();
omap.put(v1, v2);
throws CancelledException {
try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
SortedMap<Long, Long> omap = new TreeMap<>();
while (reader.hasMore()) {
pdb.checkCancelled();
long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal();
omap.put(v1, v2);
}
return omap;
}
return omap;
catch (PdbException | IOException e) {
PdbLog.message("Returning null Debug OMap due to" +
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
return null;
}
}
private List<ImageSectionHeader> deserializeSectionHeaders(int streamNum)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<ImageSectionHeader> sectionHeaders = new ArrayList<>();
while (reader.hasMore()) {
pdb.checkCancelled();
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
imageSectionHeader.parse(reader);
sectionHeaders.add(imageSectionHeader);
throws CancelledException {
try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<ImageSectionHeader> sectionHeaders = new ArrayList<>();
while (reader.hasMore()) {
pdb.checkCancelled();
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
imageSectionHeader.parse(reader);
sectionHeaders.add(imageSectionHeader);
}
return sectionHeaders;
}
catch (PdbException | IOException e) {
PdbLog.message("Returning null Debug Image Section Headers due to" +
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
return null;
}
return sectionHeaders;
}
// TODO: This is incomplete.
@ -328,55 +326,63 @@ public class DebugData {
*/
// TODO: just put a return of null Integer for now until figured out.
private Integer deserializeXData(int streamNum)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
int streamLength = reader.getLimit();
//System.out.println(reader.dump(0x20));
RvaVaDebugHeader header = new RvaVaDebugHeader();
throws CancelledException {
try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
int streamLength = reader.getLimit();
//System.out.println(reader.dump(0x20));
RvaVaDebugHeader header = new RvaVaDebugHeader();
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return null; // Silent... TODO: add logging event.
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return null; // Silent... TODO: add logging event.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug XData");
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
PdbByteReader xDataReader = reader.getSubPdbByteReader(reader.numRemaining());
// TODO: This is a partial implementation. We need to figure out more to know
// how to deal with it. The only API information regarding the XData is with
// regard to processing PData when the "machine" is IA64 or AMD64. The interpretation
// for these machines is not real clear (or a bit of work), and there is no other
// interpretation available when the machine is different.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug XData");
catch (PdbException | IOException e) {
PdbLog.message("Returning null Debug XData" +
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
return null;
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
PdbByteReader xDataReader = reader.getSubPdbByteReader(reader.numRemaining());
// TODO: This is a partial implementation. We need to figure out more to know
// how to deal with it. The only API information regarding the XData is with
// regard to processing PData when the "machine" is IA64 or AMD64. The interpretation
// for these machines is not real clear (or a bit of work), and there is no other
// interpretation available when the machine is different.
return null;
}
// TODO: This is incomplete.
private List<ImageFunctionEntry> deserializePData(int streamNum)
throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<ImageFunctionEntry> myPData = new ArrayList<>();
int streamLength = reader.getLimit();
RvaVaDebugHeader header = new RvaVaDebugHeader();
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return myPData; // Silent... TODO: add logging event.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug PData");
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
// TODO: current partial implementation does not work (throws exception)
// for ucrtbase.dll arm64. Need to look at this closer.
throws CancelledException {
try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<ImageFunctionEntry> myPData = new ArrayList<>();
int streamLength = reader.getLimit();
RvaVaDebugHeader header = new RvaVaDebugHeader();
header.deserialize(reader);
//System.out.println(header.dump());
if (header.getHeaderVersion() != 1) {
return myPData; // Silent... TODO: add logging event.
}
long headerLength = header.getHeaderLength();
long dataLength = header.getDataLength();
if (headerLength + dataLength > streamLength) {
throw new PdbException("Problem parsing Debug PData");
}
reader.setIndex((int) headerLength);
//System.out.println(reader.dump());
// TODO: current partial implementation does not work (throws exception)
// for ucrtbase.dll arm64. Need to look at this closer.
// while (reader.hasMore()) {
// pdb.checkCancelled();
// ImageFunctionEntry entry = new ImageFunctionEntry();
@ -389,23 +395,30 @@ public class DebugData {
// xDataReader.setIndex((int) index);
// //System.out.println(xDataReader.dumpBytes(0x20));
// }
// TODO: More work possible. See XData processing and notes there. This is very
// incomplete.
PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo instanceof PdbNewDebugInfo) {
//Processor target = pdb.getTargetProcessor();
PdbNewDebugInfo dbi = (PdbNewDebugInfo) debugInfo;
ImageFileMachine machine = dbi.getMachineType();
switch (machine) {
case IA64:
break;
case AMD64:
break;
default:
break;
// TODO: More work possible. See XData processing and notes there. This is very
// incomplete.
PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo instanceof PdbNewDebugInfo) {
//Processor target = pdb.getTargetProcessor();
PdbNewDebugInfo dbi = (PdbNewDebugInfo) debugInfo;
ImageFileMachine machine = dbi.getMachineType();
switch (machine) {
case IA64:
break;
case AMD64:
break;
default:
break;
}
}
return myPData;
}
return myPData;
catch (PdbException | IOException e) {
PdbLog.message("Returning null Debug PData due to" +
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
return null;
}
}
/**

View File

@ -237,8 +237,8 @@ public abstract class AbstractFunctionTypeApplier extends MsDataTypeApplier {
}
/**
* Uses {@link DefaultPdbApplicator#getDataTypeOrSchedule(Integer)}) on all underlying types
* to ensure that the types get scheduled... and detects whether any types were not yet
* Uses {@link DefaultPdbApplicator#getDataTypeOrSchedule(RecordNumber)}) on all underlying
* types to ensure that the types get scheduled... and detects whether any types were not yet
* available so that this composite type is denoted as not done.
* @param type the MS type of the function
* @return {@code true} if all underlying types are already available

View File

@ -0,0 +1,238 @@
/* ###
* 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.pdb.pdbapplicator;
import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.ClassFieldMsAttributes;
/**
*
*/
public class ClassFieldAttributes {
private static final Map<ClassFieldAttributes, ClassFieldAttributes> map = new HashMap<>();
// These initializations use the map above, so it must be initialized first
public static final ClassFieldAttributes UNKNOWN = get(Access.UNKNOWN, Property.UNKNOWN);
public static final ClassFieldAttributes BLANK = get(Access.BLANK, Property.BLANK);
private final Access access;
private final Property property;
public static ClassFieldAttributes get(Access access, Property property) {
ClassFieldAttributes key = new ClassFieldAttributes(access, property);
ClassFieldAttributes cfa = map.putIfAbsent(key, key);
return (cfa != null) ? cfa : key;
}
static ClassFieldAttributes convert(ClassFieldMsAttributes msAtts, Access defaultAccess) {
Access myAccess = switch (msAtts.getAccess()) {
case PUBLIC -> Access.PUBLIC;
case PROTECTED -> Access.PROTECTED;
case PRIVATE -> Access.PRIVATE;
case BLANK -> defaultAccess;
default -> Access.UNKNOWN;
};
Property myProperty = switch (msAtts.getProperty()) {
case VIRTUAL -> Property.VIRTUAL;
case STATIC -> Property.STATIC;
case FRIEND -> Property.FRIEND;
case BLANK -> Property.BLANK;
default -> Property.UNKNOWN;
};
return get(myAccess, myProperty);
}
private ClassFieldAttributes(Access access, Property property) {
this.access = access;
this.property = property;
}
Access getAccess() {
return access;
}
Property getProperty() {
return property;
}
void emit(StringBuilder builder) {
StringBuilder myBuilder = new StringBuilder();
if (access.getValue() > Access.BLANK.getValue()) {
myBuilder.append(access);
myBuilder.append(' ');
}
if (property.getValue() > Property.BLANK.getValue()) {
myBuilder.append(property);
myBuilder.append(' ');
}
builder.append(myBuilder);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
emit(builder);
return builder.toString();
}
@Override
public int hashCode() {
return Objects.hash(access, property);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ClassFieldAttributes other = (ClassFieldAttributes) obj;
return access == other.access && property == other.property;
}
//----------------------------------------------------------------------------------------------
// TODO: Consider expanding these beyond C++.
// See https://en.wikipedia.org/wiki/Access_modifiers
// These could then be:
// UNKNOWN("UNKNOWN_ACCESS ", -1),
// OPEN("open", 0),
// PUBLIC("internal", 1),
// INTERNAL("internal", 2),
// PACKAGE("package", 3),
// PROTECTED("protected", 4),
// PROTECTED_INTERNAL("protected internal", 5),
// PRIVATE_PROTECTED("private protected", 6),
// FILE("file", 7),
// FILE_PRIVATE("fileprivate", 8),
// PRIVATE("private", 9);
static enum Access {
UNKNOWN("UNKNOWN_ACCESS", -1),
BLANK("", 0), // eliminated 20230524... using defaultAccess on some methods. Could renumber
PUBLIC("public", 1),
PROTECTED("protected", 2),
PRIVATE("private", 3);
private static final Map<Integer, Access> BY_VALUE = new HashMap<>();
static {
for (Access val : values()) {
BY_VALUE.put(val.value, val);
}
}
private final String label;
private final int value;
public String getString() {
return label;
}
@Override
public String toString() {
return label;
}
public int getValue() {
return value;
}
public static Access fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
private Access(String label, int value) {
this.label = label;
this.value = value;
}
/**
* Merge two Access values, leaning toward more restrictive. UNKNOWN is only returned
* if both are UNKNOWN.
* @param other value to merge
* @return the merged value
*/
public Access mergeRestrictive(Access other) {
// No need to test for UNKNOWN as its value is on the permissive end.
if (this.value > other.value) {
return this;
}
return other;
}
/**
* Merge two Access values, leaning toward more permissive. UNKNOWN is only returned
* if both are UNKNOWN.
* @param other value to merge
* @return the merged value
*/
public Access mergePermissive(Access other) {
if (this.value < other.value) {
// Only need special test for UNKNOWN here, as its value is on the permissive end.
if (this == UNKNOWN) {
return other;
}
return this;
}
return other;
}
}
//----------------------------------------------------------------------------------------------
static enum Property {
UNKNOWN("INVALID_PROPERTY", -1),
BLANK("", 0), // means non-virtual, non-static, non-friend
VIRTUAL("virtual", 1),
STATIC("static", 2),
FRIEND("friend", 3);
// Also consider <intro>, <pure>, <intro,pure>. See MSFT.
private static final Map<Integer, Property> BY_VALUE = new HashMap<>();
static {
for (Property val : values()) {
BY_VALUE.put(val.value, val);
}
}
private final String label;
private final int value;
public String getString() {
return label;
}
@Override
public String toString() {
return label;
}
public int getValue() {
return value;
}
public static Property fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
private Property(String label, int value) {
this.label = label;
this.value = value;
}
}
}

View File

@ -23,6 +23,7 @@ import ghidra.app.util.SymbolPath;
import ghidra.app.util.bin.format.pdb.DefaultCompositeMember;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.*;
import ghidra.app.util.pdb.pdbapplicator.ClassFieldAttributes.Access;
import ghidra.program.model.data.*;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
@ -211,6 +212,9 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
throws PdbException, CancelledException {
AbstractCompositeMsType cType = (AbstractCompositeMsType) type;
ClassFieldAttributes.Access defaultAccess =
(type instanceof AbstractClassMsType) ? ClassFieldAttributes.Access.PRIVATE
: ClassFieldAttributes.Access.PUBLIC;
for (AbstractMsType baseType : msBases) {
applicator.checkCancelled();
@ -222,13 +226,14 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
if (baseType instanceof AbstractBaseClassMsType baseClassType) {
applyDirectBaseClass(baseClassType, myClassType);
applyDirectBaseClass(baseClassType, myClassType, defaultAccess);
}
else if (baseType instanceof AbstractVirtualBaseClassMsType virtualBaseClassType) {
applyDirectVirtualBaseClass(virtualBaseClassType, myClassType);
applyDirectVirtualBaseClass(virtualBaseClassType, myClassType, defaultAccess);
}
else if (baseType instanceof AbstractIndirectVirtualBaseClassMsType indirectVirtualBaseClassType) {
applyIndirectVirtualBaseClass(indirectVirtualBaseClassType, myClassType);
applyIndirectVirtualBaseClass(indirectVirtualBaseClassType, myClassType,
defaultAccess);
}
else {
throw new AssertException(
@ -237,7 +242,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
}
private void applyDirectBaseClass(AbstractBaseClassMsType base, CppCompositeType myClassType)
private void applyDirectBaseClass(AbstractBaseClassMsType base, CppCompositeType myClassType,
Access defaultAccess)
throws PdbException {
CppCompositeType underlyingClassType =
getUnderlyingClassType(base.getBaseClassRecordNumber());
@ -246,11 +252,12 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
ClassFieldMsAttributes atts = base.getAttributes();
int offset = applicator.bigIntegerToInt(base.getOffset());
myClassType.addDirectBaseClass(underlyingClassType, convertAttributes(atts), offset);
myClassType.addDirectBaseClass(underlyingClassType,
ClassFieldAttributes.convert(atts, defaultAccess), offset);
}
private void applyDirectVirtualBaseClass(AbstractVirtualBaseClassMsType base,
CppCompositeType myClassType) throws PdbException {
CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt =
getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) {
@ -261,12 +268,13 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
ClassFieldMsAttributes atts = base.getAttributes();
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addDirectVirtualBaseClass(underlyingCt, convertAttributes(atts),
myClassType.addDirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess),
basePointerOffset, vbtptr, offsetFromVbt);
}
private void applyIndirectVirtualBaseClass(AbstractIndirectVirtualBaseClassMsType base,
CppCompositeType myClassType) throws PdbException {
CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt =
getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) {
@ -277,7 +285,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
ClassFieldMsAttributes atts = base.getAttributes();
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addIndirectVirtualBaseClass(underlyingCt, convertAttributes(atts),
myClassType.addIndirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess),
basePointerOffset, vbtptr, offsetFromVbt);
}
@ -313,49 +322,18 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return dataType;
}
private static CppCompositeType.ClassFieldAttributes convertAttributes(
ClassFieldMsAttributes atts) {
CppCompositeType.Access myAccess;
switch (atts.getAccess()) {
case PUBLIC:
myAccess = CppCompositeType.Access.PUBLIC;
break;
case PROTECTED:
myAccess = CppCompositeType.Access.PROTECTED;
break;
case PRIVATE:
myAccess = CppCompositeType.Access.PRIVATE;
break;
default:
myAccess = CppCompositeType.Access.BLANK;
break;
}
CppCompositeType.Property myProperty;
switch (atts.getProperty()) {
case VIRTUAL:
myProperty = CppCompositeType.Property.VIRTUAL;
break;
case STATIC:
myProperty = CppCompositeType.Property.STATIC;
break;
case FRIEND:
myProperty = CppCompositeType.Property.FRIEND;
break;
default:
myProperty = CppCompositeType.Property.BLANK;
break;
}
return new CppCompositeType.ClassFieldAttributes(myAccess, myProperty);
}
private void addMembers(Composite composite, CppCompositeType myClassType,
List<AbstractMemberMsType> msMembers, AbstractCompositeMsType type,
List<DefaultPdbUniversalMember> myMembers)
throws CancelledException, PdbException {
ClassFieldAttributes.Access defaultAccess =
(type instanceof AbstractClassMsType) ? ClassFieldAttributes.Access.PRIVATE
: ClassFieldAttributes.Access.PUBLIC;
for (int index = 0; index < msMembers.size(); index++) {
applicator.checkCancelled();
AbstractMemberMsType memberType = msMembers.get(index);
DefaultPdbUniversalMember member = getNonStaticMember(composite, memberType, index);
DefaultPdbUniversalMember member =
getNonStaticMember(composite, defaultAccess, memberType, index);
DataType dt = member.getDataType().getDataType();
myMembers.add(member);
myClassType.addMember(member.getName(), dt, member.isZeroLengthArray(),
@ -386,8 +364,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
/**
* Uses {@link DefaultPdbApplicator#getDataTypeOrSchedule(Integer)}) on all underlying types
* to ensure that the types get scheduled... and detects whether any types were not yet
* Uses {@link DefaultPdbApplicator#getDataTypeOrSchedule(RecordNumber)}) on all underlying
* types to ensure that the types get scheduled... and detects whether any types were not yet
* available so that this composite type is denoted as not done.
* @param lists the lists of all underlying types
* @return {@code true} if all underlying types are already available
@ -461,14 +439,15 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
throw new PdbException("Unhandled type: " + method.getClass().getSimpleName());
}
}
for (AbstractNestedTypeMsType nested : lists.nestedTypes()) {
applicator.checkCancelled();
RecordNumber recordNumber = nested.getNestedTypeDefinitionRecordNumber();
DataType dt = applicator.getDataTypeOrSchedule(recordNumber);
if (dt == null) {
done = false;
}
}
// Might cause problems, so remove until understood and possibly needed
// for (AbstractNestedTypeMsType nested : lists.nestedTypes()) {
// applicator.checkCancelled();
// RecordNumber recordNumber = nested.getNestedTypeDefinitionRecordNumber();
// DataType dt = applicator.getDataTypeOrSchedule(recordNumber);
// if (dt == null) {
// done = false;
// }
// }
for (AbstractMemberMsType nonstaticMember : lists.nonstaticMembers()) {
applicator.checkCancelled();
RecordNumber recordNumber = nonstaticMember.getFieldTypeRecordNumber();
@ -509,7 +488,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
private DefaultPdbUniversalMember getNonStaticMember(Composite container,
AbstractMemberMsType memberMsType, int ordinal)
Access defaultAccess, AbstractMemberMsType memberMsType, int ordinal)
throws CancelledException, PdbException {
MsTypeApplier applier = applicator.getTypeApplier(memberMsType);
@ -546,7 +525,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
arrayApplier.isFlexibleArray(fieldType));
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(memberName, fieldDataType,
isZeroLengthArray, offset, convertAttributes(memberAttributes), memberComment);
isZeroLengthArray, offset,
ClassFieldAttributes.convert(memberAttributes, defaultAccess), memberComment);
return member;
}

View File

@ -252,8 +252,7 @@ public class CppCompositeType {
}
public void addVirtualFunctionTablePointer(String name, DataType dataType, int offset) {
Member newMember = new Member(name, dataType, false,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset);
Member newMember = new Member(name, dataType, false, ClassFieldAttributes.UNKNOWN, offset);
layoutVftPtrMembers.add(newMember);
}
@ -275,14 +274,14 @@ public class CppCompositeType {
public void addMember(String memberName, DataType dataType, boolean isFlexibleArray, int offset,
String comment) {
addMember(memberName, dataType, isFlexibleArray,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset, comment);
addMember(memberName, dataType, isFlexibleArray, ClassFieldAttributes.UNKNOWN, offset,
comment);
}
public void addMember(String memberName, DataType dataType, boolean isFlexibleArray,
int offset) {
addMember(memberName, dataType, isFlexibleArray,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset, null);
addMember(memberName, dataType, isFlexibleArray, ClassFieldAttributes.UNKNOWN, offset,
null);
}
public void addMember(String memberName, DataType dataType, boolean isFlexibleArray,
@ -314,14 +313,14 @@ public class CppCompositeType {
*/
public void insertMember(String memberName, DataType dataType, boolean isFlexibleArray,
int offset, String comment) {
insertMember(memberName, dataType, isFlexibleArray,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset, comment);
insertMember(memberName, dataType, isFlexibleArray, ClassFieldAttributes.UNKNOWN, offset,
comment);
}
public void insertMember(String memberName, DataType dataType, boolean isFlexibleArray,
int offset) {
insertMember(memberName, dataType, isFlexibleArray,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset, null);
insertMember(memberName, dataType, isFlexibleArray, ClassFieldAttributes.UNKNOWN, offset,
null);
}
public void insertMember(String memberName, DataType dataType, boolean isFlexibleArray,
@ -351,8 +350,7 @@ public class CppCompositeType {
}
public void addStaticMember(String memberName, DataType dataType) {
addStaticMember(memberName, dataType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN));
addStaticMember(memberName, dataType, ClassFieldAttributes.UNKNOWN);
}
public void addStaticMember(String memberName, DataType dataType,
@ -379,8 +377,7 @@ public class CppCompositeType {
}
public void addSyntacticBaseClass(CppCompositeType baseClassType) throws PdbException {
addSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN));
addSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN);
}
public void addSyntacticBaseClass(CppCompositeType baseClassType,
@ -390,8 +387,7 @@ public class CppCompositeType {
}
public void addDirectSyntacticBaseClass(CppCompositeType baseClassType) throws PdbException {
addDirectSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN));
addDirectSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN);
}
public void addDirectSyntacticBaseClass(CppCompositeType baseClassType,
@ -401,8 +397,7 @@ public class CppCompositeType {
}
public void addVirtualSyntacticBaseClass(CppCompositeType baseClassType) throws PdbException {
addVirtualSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN));
addVirtualSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN);
}
public void addVirtualSyntacticBaseClass(CppCompositeType baseClassType,
@ -413,8 +408,7 @@ public class CppCompositeType {
public void insertSyntacticBaseClass(CppCompositeType baseClassType, int ordinal)
throws PdbException {
insertSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), ordinal);
insertSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, ordinal);
}
public void insertSyntacticBaseClass(CppCompositeType baseClassType,
@ -429,8 +423,7 @@ public class CppCompositeType {
public void insertDirectSyntacticBaseClass(CppCompositeType baseClassType, int ordinal)
throws PdbException {
insertDirectSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), ordinal);
insertDirectSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, ordinal);
}
public void insertDirectSyntacticBaseClass(CppCompositeType baseClassType,
@ -445,8 +438,7 @@ public class CppCompositeType {
public void insertVirtualSyntacticBaseClass(CppCompositeType baseClassType, int ordinal)
throws PdbException {
insertVirtualSyntacticBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), ordinal);
insertVirtualSyntacticBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, ordinal);
}
public void insertVirtualSyntacticBaseClass(CppCompositeType baseClassType,
@ -461,8 +453,7 @@ public class CppCompositeType {
//==============================================================================================
public void addDirectBaseClass(CppCompositeType baseClassType, int offset) throws PdbException {
addDirectBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), offset);
addDirectBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, offset);
}
public void addDirectBaseClass(CppCompositeType baseClassType, ClassFieldAttributes attributes,
@ -491,9 +482,8 @@ public class CppCompositeType {
//
public void addDirectVirtualBaseClass(CppCompositeType baseClassType, int basePointerOffset,
DataType vbptr, int offsetFromVbt) throws PdbException {
addDirectVirtualBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), basePointerOffset, vbptr,
offsetFromVbt);
addDirectVirtualBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, basePointerOffset,
vbptr, offsetFromVbt);
}
public void addDirectVirtualBaseClass(CppCompositeType baseClassType,
@ -524,9 +514,8 @@ public class CppCompositeType {
//
public void addIndirectVirtualBaseClass(CppCompositeType baseClassType, int basePointerOffset,
DataType vbptr, int offsetFromVbt) throws PdbException {
addIndirectVirtualBaseClass(baseClassType,
new ClassFieldAttributes(Access.UNKNOWN, Property.UNKNOWN), basePointerOffset, vbptr,
offsetFromVbt);
addIndirectVirtualBaseClass(baseClassType, ClassFieldAttributes.UNKNOWN, basePointerOffset,
vbptr, offsetFromVbt);
}
public void addIndirectVirtualBaseClass(CppCompositeType baseClassType,
@ -947,7 +936,8 @@ public class CppCompositeType {
}
boolean allVbtFound = true;
for (Entry<Integer, PlaceholderVirtualBaseTable> tableEntry : placeholderVirtualBaseTables.entrySet()) {
for (Entry<Integer, PlaceholderVirtualBaseTable> tableEntry : placeholderVirtualBaseTables
.entrySet()) {
int vbtptrOffset = tableEntry.getKey();
PlaceholderVirtualBaseTable table = tableEntry.getValue();
if (!table.validateOffset()) {
@ -1736,7 +1726,8 @@ public class CppCompositeType {
}
PlaceholderVirtualBaseTableEntry getEntryByName(String nameParam) {
for (Entry<Integer, PlaceholderVirtualBaseTableEntry> entry : entriesByIndex.entrySet()) {
for (Entry<Integer, PlaceholderVirtualBaseTableEntry> entry : entriesByIndex
.entrySet()) {
if (nameParam.equals(
entry.getValue().getVirtualBaseClass().getBaseClassType().getName())) {
return entry.getValue();
@ -1749,36 +1740,6 @@ public class CppCompositeType {
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
static class ClassFieldAttributes {
Access access;
Property property;
ClassFieldAttributes(Access access, Property property) {
this.access = access;
this.property = property;
}
private Access getAccess() {
return access;
}
private Property getProperty() {
return property;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (access.getValue() > Access.BLANK.getValue()) {
builder.append(access);
}
if (property.equals(Property.VIRTUAL)) {
builder.append(property);
}
return builder.toString();
}
}
//----------------------------------------------------------------------------------------------
static enum Type {
UNKNOWN("UNKNOWN_TYPE", -1),
@ -1822,91 +1783,4 @@ public class CppCompositeType {
}
}
//----------------------------------------------------------------------------------------------
static enum Access {
UNKNOWN("UNKNOWN_ACCESS ", -1),
BLANK("", 0),
PUBLIC("public", 1),
PROTECTED("protected", 2),
PRIVATE("private", 3);
private static final Map<Integer, Access> BY_VALUE = new HashMap<>();
static {
for (Access val : values()) {
BY_VALUE.put(val.value, val);
}
}
private final String label;
private final int value;
public String getString() {
return label;
}
@Override
public String toString() {
if (label.length() != 0) {
return label + " ";
}
return label;
}
public int getValue() {
return value;
}
public static Access fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
private Access(String label, int value) {
this.label = label;
this.value = value;
}
}
//----------------------------------------------------------------------------------------------
static enum Property {
UNKNOWN("INVALID_PROPERTY", -1),
BLANK("", 0),
VIRTUAL("virtual ", 1),
STATIC("static ", 2),
FRIEND("friend ", 3);
// Also consider <intro>, <pure>, <intro,pure>. See MSFT.
private static final Map<Integer, Property> BY_VALUE = new HashMap<>();
static {
for (Property val : values()) {
BY_VALUE.put(val.value, val);
}
}
private final String label;
private final int value;
public String getString() {
return label;
}
@Override
public String toString() {
if (label.length() != 0) {
return label + " ";
}
return label;
}
public int getValue() {
return value;
}
public static Property fromValue(int val) {
return BY_VALUE.getOrDefault(val, UNKNOWN);
}
private Property(String label, int value) {
this.label = label;
this.value = value;
}
}
}

View File

@ -4,9 +4,9 @@
* 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.
@ -15,7 +15,6 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
import java.io.IOException;
import java.math.BigInteger;
import java.util.*;
@ -197,12 +196,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @param logParam the MessageLog to which to output messages
* @throws PdbException if there was a problem processing the data
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
public void applyTo(Program programParam, DataTypeManager dataTypeManagerParam,
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
MessageLog logParam) throws PdbException, CancelledException, IOException {
MessageLog logParam) throws PdbException, CancelledException {
// FIXME: should not support use of DataTypeManager-only since it will not have the correct
// data organization if it corresponds to a data type archive. Need to evaluate archive
@ -420,12 +417,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
* Initializes helper classes and data items used for applying the PDB
* @throws CancelledException upon user cancellation
* @throws PdbException upon error in processing components
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
private void initializeApplyTo(Program programParam, DataTypeManager dataTypeManagerParam,
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
MessageLog logParam) throws PdbException, CancelledException, IOException {
MessageLog logParam) throws PdbException, CancelledException {
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, logParam);
@ -846,7 +841,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
if (dt != null) {
return dt;
}
multiphaseResolver.scheduleTodo(recordNumber);
multiphaseResolver.scheduleTodo(mappedNumber);
return null;
}

View File

@ -16,7 +16,6 @@
package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb.*;
import ghidra.app.util.pdb.pdbapplicator.CppCompositeType.*;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.CancelledException;
@ -30,9 +29,6 @@ public class DefaultPdbUniversalMember extends PdbMember {
private ClassFieldAttributes attributes;
private boolean isZeroLengthArray;
private static final ClassFieldAttributes blankAtttributes =
new ClassFieldAttributes(Access.BLANK, Property.BLANK);
/**
* Default PDB member construction
* @param name member field name. For bitfields this also conveys the bit-size
@ -43,7 +39,7 @@ public class DefaultPdbUniversalMember extends PdbMember {
DefaultPdbUniversalMember(String name, DataType dataType, int offset) {
super(name, dataType.getName(), offset, null);
this.dataType = dataType;
this.attributes = blankAtttributes;
this.attributes = ClassFieldAttributes.BLANK;
this.isZeroLengthArray = false;
}

View File

@ -4,9 +4,9 @@
* 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.
@ -16,20 +16,9 @@
package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
import ghidra.program.model.data.DataType;
/**
* Abstract class representing the applier for a specific PDB_ID type. The
* {@link #apply(AbstractMsType type, FixupContext fixupContext, boolean breakCycle)} method
* creates an associated {@link DataType}, if applicable, The latter of these forces the
* creation of the defined type when and forward reference type is not appropriate for the
* consumer. Note that this should only be used when sanctioned and not on a whim. Currently,
* such situations include when ghidra needs a defined type for the underlying type of an array,
* when used as a base class of a class or when needed as a member of another class/composite.
* Methods associated with the {@link MsTypeApplier} or derived class will
* make fields available to the user, first by trying to get them from the {@link DataType},
* otherwise getting them from the {@link AbstractMsType} argument.
* Abstract class representing the applier for a specific PDB_ID type.
*/
public abstract class MsTypeApplier {

View File

@ -59,6 +59,8 @@ public class MultiphaseDataTypeResolver {
if (applicator.getDataType(recordNumber) != null) {
return;
}
// Location where one might do conditional: todoStack.setDebug(true)
// If not in the map, it will also not be in the todo or resolve stacks, as both
// should be empty at this point.
scheduleTodo(recordNumber);
@ -81,6 +83,7 @@ public class MultiphaseDataTypeResolver {
resolveStack.push(recordToProcess);
}
}
// If set true above, location where one might do conditional: todoStack.setDebug(false)
// Pop top of stack and work on it.
while ((recordToProcess = resolveStack.pop()) != null) {
@ -134,13 +137,21 @@ public class MultiphaseDataTypeResolver {
private RecordNode(RecordNumber recordNumber) {
this.recordNumber = recordNumber;
}
@Override
public String toString() {
return recordNumber.toString();
}
}
static final int TO_STRING_LIMIT = 500;
static final RecordNumber HEAD = RecordNumber.typeRecordNumber(-1);
static final RecordNumber TAIL = RecordNumber.typeRecordNumber(-2);
Map<RecordNumber, RecordNode> map;
RecordNode head;
RecordNode tail;
boolean debug;
StringBuilder debugBuilder;
/**
* Constructor for new record stack
@ -156,6 +167,14 @@ public class MultiphaseDataTypeResolver {
tail.prev = null;
}
/**
* Set or clear developer debug
* @param debug {@code true} to turn on; {@code false} to turn off
*/
void setDebug(boolean debug) {
this.debug = debug;
}
/**
* Indicates if number number exists on stack
* @param recordNumber the record number to check
@ -177,6 +196,14 @@ public class MultiphaseDataTypeResolver {
}
if (node == null) {
node = new RecordNode(recordNumber);
if (debug) {
if (map.isEmpty()) {
debugBuilder = new StringBuilder();
}
debugBuilder.append("push:");
debugBuilder.append(recordNumber);
debugBuilder.append("\n");
}
map.put(recordNumber, node);
}
else { // already exists in non-top-of-stack position
@ -208,6 +235,14 @@ public class MultiphaseDataTypeResolver {
}
removeNodeLinkage(node);
map.remove(node.recordNumber);
if (debug) {
debugBuilder.append(" pop:");
debugBuilder.append(node.recordNumber);
debugBuilder.append("\n");
if (map.isEmpty()) {
System.out.println(debugBuilder.toString());
}
}
return node.recordNumber;
}
@ -249,6 +284,27 @@ public class MultiphaseDataTypeResolver {
node.next = null;
}
@Override
public String toString() {
int count = 0;
RecordNode node = head.prev;
StringBuilder builder = new StringBuilder();
builder.append('[');
while (node != tail && count < TO_STRING_LIMIT) {
if (count != 0) {
builder.append(",");
}
builder.append(node);
node = node.prev;
count++;
}
if (node != tail) {
builder.append("...");
}
builder.append(']');
return builder.toString();
}
}
}

View File

@ -15,7 +15,6 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
import java.io.IOException;
import java.util.*;
import org.apache.commons.collections4.CollectionUtils;
@ -36,7 +35,7 @@ abstract class PdbAddressCalculator {
private int maxSegment;
static PdbAddressCalculator chooseAddressCalculator(PdbApplicator applicator, Address imageBase)
throws CancelledException, PdbException, IOException {
throws CancelledException, PdbException {
AbstractPdb pdb = applicator.getPdb();
PdbDebugInfo dbi = pdb.getDebugInfo();

View File

@ -15,7 +15,6 @@
*/
package ghidra.app.util.pdb.pdbapplicator;
import java.io.IOException;
import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
@ -80,11 +79,9 @@ public class PdbAddressManager {
* @param imageBase Address from which all other addresses are based.
* @throws PdbException If Program is null;
* @throws CancelledException upon user cancellation
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
PdbAddressManager(DefaultPdbApplicator applicator, Address imageBase)
throws PdbException, CancelledException, IOException {
throws PdbException, CancelledException {
Objects.requireNonNull(applicator, "applicator may not be null");
Objects.requireNonNull(imageBase, "imageBase may not be null");
this.applicator = applicator;
@ -342,11 +339,8 @@ public class PdbAddressManager {
/**
* Determines memory blocks
* @throws CancelledException upon user cancellation
* @throws PdbException upon error in processing components
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes
*/
private void determineMemoryBlocks() throws CancelledException, PdbException, IOException {
private void determineMemoryBlocks() throws CancelledException {
AbstractPdb pdb = applicator.getPdb();
PdbDebugInfo debugInfo = pdb.getDebugInfo();
segmentMapList = debugInfo.getSegmentMapList();

View File

@ -36,12 +36,12 @@ import ghidra.util.task.TaskMonitor;
*
*
*/
public class ConflictHandlerTest2 extends AbstractGhidraHeadedIntegrationTest {
public class ConflictHandler2Test extends AbstractGhidraHeadedIntegrationTest {
private ProgramDB program;
private DataTypeManagerDB dtm;
private int transactionID;
public ConflictHandlerTest2() {
public ConflictHandler2Test() {
super();
}
@ -137,7 +137,7 @@ public class ConflictHandlerTest2 extends AbstractGhidraHeadedIntegrationTest {
}
try {
if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, size, members,
msg -> Msg.warn(ConflictHandlerTest2.class, msg), monitor)) {
msg -> Msg.warn(ConflictHandler2Test.class, msg), monitor)) {
((Structure) composite).deleteAll();
}
}