Merge branch 'GP-1104_ghizard_Fix_PDB_CLI_processing_bug' into patch

This commit is contained in:
ghidra1 2021-07-08 13:16:19 -04:00
commit 3c1e51d0c0
2 changed files with 90 additions and 19 deletions

View File

@ -439,6 +439,23 @@ public class PdbApplicator {
Msg.info(originator, message);
}
/**
* Puts error message to {@link PdbLog} and to Msg.error() which will
* also log a stack trace if exception is specified.
* @param originator a Logger instance, "this", or YourClass.class
* @param message the error message to display/log
* @param exc exception whose stack trace should be reported or null
*/
void pdbLogAndErrorMessage(Object originator, String message, Exception exc) {
PdbLog.message(message);
if (exc != null) {
Msg.error(originator, message);
}
else {
Msg.error(originator, message, exc);
}
}
/**
* Returns the {@link TaskMonitor} to available for this analyzer.
* @return the monitor.
@ -928,6 +945,7 @@ public class PdbApplicator {
//==============================================================================================
// CLI-Managed infor methods.
//==============================================================================================
// Currently in CLI, but could move.
boolean isDll() {
return pdbCliManagedInfoManager.isDll();
@ -938,6 +956,15 @@ public class PdbApplicator {
return pdbCliManagedInfoManager.isAslr();
}
/**
* Get CLI metadata for specified tableNum and rowNum within the CLI
* metadata stream.
* @param tableNum CLI metadata stream table index
* @param rowNum table row number
* @return CLI metadata or null if specified tableNum not found
* @throws PdbException if CLI metadata stream is not found in program file bytes
* @throws IndexOutOfBoundsException if specified rowNum is invalid
*/
CliAbstractTableRow getCliTableRow(int tableNum, int rowNum) throws PdbException {
return pdbCliManagedInfoManager.getCliTableRow(tableNum, rowNum);
}

View File

@ -37,6 +37,9 @@ import ghidra.program.model.listing.Program;
*/
public class PdbCliInfoManager {
private PdbApplicator applicator;
private boolean initComplete = false;
private CliStreamMetadata metadataStream;
// TODO: May move these out from this class to a higher level. Would mean passing in
@ -46,22 +49,43 @@ public class PdbCliInfoManager {
/**
* Manager of CLI-related tables that we might need access to for PDB processing.
* @param applicator {@link PdbApplicator} for which this class is working.
* @param applicator {@link PdbApplicator} for which this class is working (used for logging purposes only).
*/
PdbCliInfoManager(PdbApplicator applicator) {
Objects.requireNonNull(applicator, "applicator may not be null");
metadataStream = getCliStreamMetadata(applicator);
this.applicator = applicator;
}
private synchronized void initialize() {
if (initComplete) {
return;
}
initComplete = true;
metadataStream = getCliStreamMetadata();
}
boolean isDll() {
initialize();
return isDll;
}
boolean isAslr() {
initialize();
return isAslr;
}
CliAbstractTableRow getCliTableRow(int tableNum, int rowNum) throws PdbException {
/**
* Get CLI metadata for specified tableNum and rowNum within the CLI
* metadata stream.
* @param tableNum CLI metadata stream table index
* @param rowNum table row number
* @return CLI metadata or null if specified tableNum not found
* @throws PdbException if CLI metadata stream is not found in program file bytes
* @throws IndexOutOfBoundsException if specified rowNum is invalid
*/
CliAbstractTableRow getCliTableRow(int tableNum, int rowNum)
throws PdbException, IndexOutOfBoundsException {
initialize();
if (metadataStream == null) {
throw new PdbException("CliStreamMetadata is null");
}
@ -72,21 +96,34 @@ public class PdbCliInfoManager {
return table.getRow(rowNum);
}
private CliStreamMetadata getCliStreamMetadata(PdbApplicator applicator) {
/**
* Get CLI stream metadata
* @return CLI stream metadata or null if not found or error occured
*/
private CliStreamMetadata getCliStreamMetadata() {
Program program = applicator.getProgram();
if (program == null) {
return null;
}
List<FileBytes> allFileBytes = program.getMemory().getAllFileBytes();
if (allFileBytes.isEmpty()) {
applicator.pdbLogAndErrorMessage(this,
"Unable to retrieve CliStreamMetadata: no FileBytes", null);
return null;
}
FileBytes fileBytes = allFileBytes.get(0); // Should be that of main imported file
ByteProvider provider = new FileBytesProvider(fileBytes);
PortableExecutable pe = null;
ByteProvider provider = new FileBytesProvider(fileBytes); // close not required
try {
GenericFactory factory = MessageLogContinuesFactory.create(applicator.getMessageLog());
pe = PortableExecutable.createPortableExecutable(factory, provider, SectionLayout.FILE,
true, true);
NTHeader ntHeader = pe.getNTHeader();
PortableExecutable pe = PortableExecutable.createPortableExecutable(factory, provider,
SectionLayout.FILE, true, true);
NTHeader ntHeader = pe.getNTHeader(); // will be null if header parse fails
if (ntHeader == null) {
applicator.pdbLogAndErrorMessage(this,
"Unable to retrieve CliStreamMetadata: NTHeader file bytes not found", null);
return null;
}
OptionalHeader optionalHeader = ntHeader.getOptionalHeader();
int characteristics = ntHeader.getFileHeader().getCharacteristics();
isDll = (characteristics & FileHeader.IMAGE_FILE_DLL) == FileHeader.IMAGE_FILE_DLL;
@ -94,25 +131,32 @@ public class PdbCliInfoManager {
int optionalHeaderCharaceristics = optionalHeader.getDllCharacteristics();
isAslr = (optionalHeaderCharaceristics &
OptionalHeader.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == OptionalHeader.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA;
if (OptionalHeader.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR >= dataDirectory.length) {
applicator.pdbLogAndErrorMessage(this,
"Unable to retrieve CliStreamMetadata: Bad index (" +
OptionalHeader.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR +
") for COMDescriptorDataDirectory in DataDirectory array of size " +
dataDirectory.length,
null);
return null;
}
COMDescriptorDataDirectory comDir =
(COMDescriptorDataDirectory) dataDirectory[OptionalHeader.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
ImageCor20Header header = comDir.getHeader();
if (header == null) {
applicator.pdbLogAndErrorMessage(this,
"Unable to retrieve CliStreamMetadata: no COMDir header", null);
return null;
}
return header.getMetadata().getMetadataRoot().getMetadataStream();
}
catch (Exception e) {
applicator.pdbLogAndInfoMessage(this, "Unable to retrieve CliStreamMetadata");
catch (RuntimeException | IOException e) {
// We do not know what can go wrong. Some of the header parsing might have issues,
// and we'd rather log the error and limp on by with whatever other processing we can
// do than to fail here.
applicator.pdbLogAndErrorMessage(this,
"Unable to retrieve CliStreamMetadata: " + e.getMessage(), e);
return null;
}
finally {
try {
provider.close();
}
catch (IOException ioe) {
applicator.pdbLogAndInfoMessage(this, "Problem closing ByteProvider");
}
}
}
}