mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 13:11:47 +00:00
GP-5072 - PDB - Progress on fixing up the processing of older PDB
versions
This commit is contained in:
parent
7ddd8665b7
commit
fb15252442
@ -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.
|
||||
@ -19,7 +19,6 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
||||
@ -246,11 +245,9 @@ public abstract class AbstractSymbolInformation {
|
||||
}
|
||||
|
||||
protected void deserializeHashHeader() throws PdbException, CancelledException, IOException {
|
||||
MsfStream stream = pdb.getMsf().getStream(streamNumber);
|
||||
PdbByteReader reader =
|
||||
pdb.getReaderForStreamNumber(streamNumber, symbolHashOffset,
|
||||
HASH_HEADER_MIN_READ_LENGTH);
|
||||
deserializeHashHeader(reader, stream.getLength());
|
||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, symbolHashOffset,
|
||||
HASH_HEADER_MIN_READ_LENGTH);
|
||||
deserializeHashHeader(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,7 +255,7 @@ public abstract class AbstractSymbolInformation {
|
||||
* @param reader {@link PdbByteReader} containing the data buffer to process
|
||||
* @throws PdbException upon not enough data left to parse
|
||||
*/
|
||||
private void deserializeHashHeader(PdbByteReader reader, int streamLength) throws PdbException {
|
||||
private void deserializeHashHeader(PdbByteReader reader) throws PdbException {
|
||||
headerSignature = reader.parseInt();
|
||||
if (headerSignature == HEADER_SIGNATURE) {
|
||||
hashHeaderLength = HASH_70_HEADER_LENGTH;
|
||||
@ -273,10 +270,10 @@ public abstract class AbstractSymbolInformation {
|
||||
reader.reset(); // There was no header
|
||||
// Calculate the values
|
||||
bucketsLength = 4 * (numHashRecords + 1);
|
||||
if (streamLength < bucketsLength) {
|
||||
if (symbolHashLength < bucketsLength) {
|
||||
throw new PdbException("Not enough data for symbol hash buckets.");
|
||||
}
|
||||
hashRecordsLength = streamLength - bucketsLength;
|
||||
hashRecordsLength = symbolHashLength - bucketsLength;
|
||||
hashRecordsOffset = symbolHashOffset + 0;
|
||||
bucketsOffset = hashRecordsOffset + hashRecordsLength;
|
||||
}
|
||||
|
@ -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.
|
||||
@ -33,7 +33,6 @@ public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
|
||||
@Override
|
||||
protected int getStreamNumber() {
|
||||
return ITEM_PROGRAM_INTERFACE_STREAM_NUMBER;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +43,24 @@ public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
|
||||
@Override
|
||||
protected RecordCategory getCategory() {
|
||||
return RecordCategory.ITEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a reasonable error when searching for a version number. For
|
||||
* the standard TPI case, any unrecognized version number is a reasonable error. For this
|
||||
* IPI case, we have to be able to error on an unrecognized version number, so we report
|
||||
* true for version numbers that would seem reasonable. We return false if the versionNumber
|
||||
* is not a reasonable number, which allows the "hack" to work for IPI where a failure to
|
||||
* parse an IPI is an indication that there is no IPI (which is first screened by the
|
||||
* {@link #hackCheckNoNameForStream(NameTable)} method
|
||||
* @param versionNumber the versionNumber being checked
|
||||
* @return {@code true} if the error is a reasonable error
|
||||
*/
|
||||
@Override
|
||||
protected boolean isReasonableError(int versionNumber) {
|
||||
String str = String.format("%d", versionNumber);
|
||||
return (str.length() == 8 &&
|
||||
(str.startsWith("199") || str.startsWith("200") || str.startsWith("201")));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
@ -344,6 +344,7 @@ public abstract class PdbDebugInfo {
|
||||
// DebugInfo and if the above part (test for SVC600 and SVC1400 would
|
||||
// be the override method for PdbNewDebugInfo.
|
||||
else {
|
||||
substreamReader.reset(); // version number was not a real field
|
||||
while (substreamReader.hasMore()) {
|
||||
pdb.checkCancelled();
|
||||
SectionContribution sectionContribution = new SectionContribution400();
|
||||
|
@ -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.
|
||||
@ -27,7 +27,7 @@ import ghidra.util.exception.CancelledException;
|
||||
*/
|
||||
public class PdbOldDebugInfo extends PdbDebugInfo {
|
||||
|
||||
private static final int OLD_DBI_HEADER_LENGTH = 22;
|
||||
private static final int OLD_DBI_HEADER_LENGTH = 24;
|
||||
|
||||
//==============================================================================================
|
||||
// API
|
||||
@ -49,6 +49,7 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
|
||||
streamNumberGlobalStaticSymbolsHashMaybe = reader.parseUnsignedShortVal();
|
||||
streamNumberPublicStaticSymbolsHashMaybe = reader.parseUnsignedShortVal();
|
||||
streamNumberSymbolRecords = reader.parseUnsignedShortVal();
|
||||
reader.skip(2); // padding between previous unsigned short and next-to-read int
|
||||
lengthModuleInformationSubstream = reader.parseInt();
|
||||
lengthSectionContributionSubstream = reader.parseInt();
|
||||
lengthSectionMap = reader.parseInt();
|
||||
|
@ -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.
|
||||
@ -29,11 +29,12 @@ public class SectionContribution400 extends SectionContribution {
|
||||
@Override
|
||||
void deserialize(PdbByteReader reader) throws PdbException {
|
||||
isect = reader.parseUnsignedShortVal();
|
||||
reader.parseBytes(2); // I think there is padding here.
|
||||
reader.skip(2); // Padding
|
||||
offset = reader.parseInt();
|
||||
length = reader.parseInt();
|
||||
characteristics = reader.parseUnsignedIntVal();
|
||||
imod = reader.parseUnsignedShortVal();
|
||||
reader.skip(2); // Padding
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.
|
||||
@ -189,17 +189,21 @@ public class SymbolRecords {
|
||||
catch (IOException e) {
|
||||
throw new PdbException("PDB Error: Not enough data to read CvSigLength");
|
||||
}
|
||||
if (getSig) {
|
||||
cvSignature = reader.parseInt();
|
||||
}
|
||||
// 20241029: Neutering this for now; msft-intended logic still not quite understood
|
||||
// if (getSig) {
|
||||
// cvSignature = reader.parseInt();
|
||||
// }
|
||||
cvSignature = reader.parseInt(); // 20241029: in place of neutered code
|
||||
int size = 0;
|
||||
switch (cvSignature) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (streamNumber == cvSignatureCase1and2Stream) {
|
||||
size = 4;
|
||||
}
|
||||
// else size remains 0
|
||||
// 20241029: Neutering this for now; msft-intended logic still not quite understood
|
||||
// if (streamNumber == cvSignatureCase1and2Stream) {
|
||||
// size = 4;
|
||||
// }
|
||||
// // else size remains 0
|
||||
size = 4; // 20241029: in place of neutered code
|
||||
break;
|
||||
case 4:
|
||||
size = 4;
|
||||
@ -295,7 +299,15 @@ public class SymbolRecords {
|
||||
try {
|
||||
PdbByteReader reader;
|
||||
reader = pdb.getReaderForStreamNumber(streamNumber, offset, 2);
|
||||
int recordLength = reader.parseUnsignedShortVal();
|
||||
int recordLength;
|
||||
try {
|
||||
recordLength = reader.parseUnsignedShortVal();
|
||||
}
|
||||
catch (PdbException pe) {
|
||||
// Catching this PdbException due to not more data, but letting one from parse()
|
||||
// (below) get passed to caller
|
||||
return null;
|
||||
}
|
||||
// offset + 2 where 2 is sizeof(short)
|
||||
PdbByteReader recordReader =
|
||||
pdb.getReaderForStreamNumber(streamNumber, offset + 2, recordLength);
|
||||
|
@ -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.
|
||||
@ -90,7 +90,19 @@ public class TypeProgramInterfaceParser {
|
||||
new TypeProgramInterface800(pdb, getCategory(), streamNumber);
|
||||
break;
|
||||
default:
|
||||
throw new PdbException("Unknown TPI Version: " + versionNumber);
|
||||
// See MSFT "doc" pdb.cpp OpenIpi() note regarding hack.
|
||||
// For IPI, if normal stream number exists and it is unnamed, then try to
|
||||
// parse it, and accept it if no errors. However, at this point, this would
|
||||
// be considered an error here. But we want to be careful about killing
|
||||
// PDB parsing here for this case. So we have added the isReasonableError()
|
||||
// check here, which always returns true for TPI, but does special checking
|
||||
// for IPI. If IPI says it is not a reasonable error (version number looks like
|
||||
// a non-version number and it is an API), then we must presume that the stream
|
||||
// is not really an IPI stream and just return null.
|
||||
if (isReasonableError(versionNumber)) {
|
||||
throw new PdbException("Unknown TPI Version: " + versionNumber);
|
||||
}
|
||||
typeProgramInterface = null;
|
||||
}
|
||||
|
||||
return typeProgramInterface;
|
||||
@ -117,4 +129,16 @@ public class TypeProgramInterfaceParser {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a reasonable error when searching for a version number. For
|
||||
* the standard TPI case, any unrecognized version number is a reasonable error. This
|
||||
* method gets overridden in IPI for the hack situation described earlier in the default
|
||||
* case above
|
||||
* @param versionNumber the versionNumber being checked
|
||||
* @return {@code true} if the error is a reasonable error
|
||||
*/
|
||||
protected boolean isReasonableError(int versionNumber) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1643,7 +1643,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
while (iter.hasNext()) {
|
||||
monitor.checkCancelled();
|
||||
procSymNew(iter);
|
||||
monitor.incrementProgress(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2033,22 +2032,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
return;
|
||||
}
|
||||
|
||||
int totalCount = 0;
|
||||
int num = debugInfo.getNumModules();
|
||||
for (int index = 1; index <= num; index++) {
|
||||
monitor.checkCancelled();
|
||||
if (index == linkerModuleNumber) {
|
||||
continue;
|
||||
}
|
||||
SymbolGroup symbolGroup = getSymbolGroupForModule(index);
|
||||
if (symbolGroup == null) {
|
||||
continue; // should not happen
|
||||
}
|
||||
//totalCount += symbolGroup.size();
|
||||
totalCount++;
|
||||
}
|
||||
monitor.setMessage("PDB: Processing module thunks...");
|
||||
monitor.initialize(totalCount);
|
||||
monitor.initialize(num);
|
||||
|
||||
// Process symbols list for each module
|
||||
for (int index = 1; index <= num; index++) {
|
||||
@ -2070,7 +2056,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||
else {
|
||||
iter.next();
|
||||
}
|
||||
//monitor.incrementProgress(1);
|
||||
}
|
||||
monitor.incrementProgress(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user