mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 02:22:05 +08:00
Merge remote-tracking branch 'origin/GP-5664_ghizard_PdbReader_parse_NewFramePointerOmission_data'
This commit is contained in:
+51
-1
@@ -47,7 +47,8 @@ public class DebugData {
|
|||||||
X_DATA(7),
|
X_DATA(7),
|
||||||
P_DATA(8),
|
P_DATA(8),
|
||||||
NEW_FRAME_POINTER_OMISSION(9),
|
NEW_FRAME_POINTER_OMISSION(9),
|
||||||
SECTION_HEADER_ORIG(10);
|
SECTION_HEADER_ORIG(10),
|
||||||
|
UNKNOWN_DEBUG_11(11); // should be renamed when identified
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
@@ -180,6 +181,20 @@ public class DebugData {
|
|||||||
return deserializeSectionHeaders(streamNum);
|
return deserializeSectionHeaders(streamNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the New Frame Pointer Omission data (FrameDataRecord)
|
||||||
|
* @return the frame data or null if does not exist or problem parsing
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
public List<FrameDataRecord> getNewFramePointerOmissionData()
|
||||||
|
throws CancelledException {
|
||||||
|
int streamNum = getDebugStream(DebugType.NEW_FRAME_POINTER_OMISSION);
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeNewFramePointerOmissionData(streamNum);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize {@link DebugData} header from the {@link PdbByteReader} input. This parses
|
* Deserialize {@link DebugData} header from the {@link PdbByteReader} input. This parses
|
||||||
* stream numbers for varying Debug Types--the order/location of the stream number is for
|
* stream numbers for varying Debug Types--the order/location of the stream number is for
|
||||||
@@ -259,6 +274,9 @@ public class DebugData {
|
|||||||
case SECTION_HEADER_ORIG:
|
case SECTION_HEADER_ORIG:
|
||||||
// imageSectionHeadersOrig = deserializeSectionHeaders(streamNum);
|
// imageSectionHeadersOrig = deserializeSectionHeaders(streamNum);
|
||||||
break;
|
break;
|
||||||
|
case UNKNOWN_DEBUG_11:
|
||||||
|
// unknown
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +444,28 @@ public class DebugData {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<FrameDataRecord> deserializeNewFramePointerOmissionData(int streamNum)
|
||||||
|
throws CancelledException {
|
||||||
|
// TODO: check implementation for completeness.
|
||||||
|
try {
|
||||||
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
|
||||||
|
List<FrameDataRecord> frameData = new ArrayList<>();
|
||||||
|
while (reader.hasMore()) {
|
||||||
|
pdb.checkCancelled();
|
||||||
|
FrameDataRecord frameDataRecord = new FrameDataRecord();
|
||||||
|
frameDataRecord.parse(reader);
|
||||||
|
frameData.add(frameDataRecord);
|
||||||
|
}
|
||||||
|
return frameData;
|
||||||
|
}
|
||||||
|
catch (PdbException | IOException e) {
|
||||||
|
//catch (IOException e) {
|
||||||
|
PdbLog.message("Returning null Debug New Frame Pointer Omission Data due to" +
|
||||||
|
" problem during deserialization from stream" + streamNum + ": " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps the {@link DebugData}. This package-protected method is for debugging only
|
* Dumps the {@link DebugData}. This package-protected method is for debugging only
|
||||||
* @param writer {@link Writer} to which to write the debug dump
|
* @param writer {@link Writer} to which to write the debug dump
|
||||||
@@ -504,6 +544,16 @@ public class DebugData {
|
|||||||
}
|
}
|
||||||
writer.write("End PData---------------------------------------------------\n");
|
writer.write("End PData---------------------------------------------------\n");
|
||||||
|
|
||||||
|
writer.write("NewFramePointerOmissionData---------------------------------\n");
|
||||||
|
List<FrameDataRecord> frameData = getNewFramePointerOmissionData();
|
||||||
|
if (frameData != null) {
|
||||||
|
for (FrameDataRecord frameDataRecord : frameData) {
|
||||||
|
pdb.checkCancelled();
|
||||||
|
frameDataRecord.dump(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write("End NewFramePointerOmissionData-----------------------------\n");
|
||||||
|
|
||||||
writer.write("End DebugData-----------------------------------------------\n");
|
writer.write("End DebugData-----------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+183
@@ -0,0 +1,183 @@
|
|||||||
|
/* ###
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FRAMEDATA from cvinfo.h
|
||||||
|
* Most members are coded as unsigned long or unsigned long bit-fields; two are coded as
|
||||||
|
* unsigned short: prolog and saved regs.
|
||||||
|
*/
|
||||||
|
public class FrameDataRecord {
|
||||||
|
|
||||||
|
private long rvaStart; // unsigned long
|
||||||
|
private long numBlockBytes; // unsigned long
|
||||||
|
private long numLocalBytes; // unsigned long
|
||||||
|
private long numParamBytes; // unsigned long
|
||||||
|
private long maxStackBytes; // unsigned long
|
||||||
|
private long frameFunc; // ? // unsigned long
|
||||||
|
private int numPrologBytes; // unsigned short
|
||||||
|
private int numSavedRegBytes; // unsigned short
|
||||||
|
private boolean hasSEH; // unsigned long bit-field
|
||||||
|
private boolean hasEH; // unsigned long bit-field
|
||||||
|
private boolean isFunctionStart; // unsigned long bit-field
|
||||||
|
private long reserved; // contains shifted/masked remainder of unsigned long
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the RVA start
|
||||||
|
* @return the RVA start
|
||||||
|
*/
|
||||||
|
public long getRvaStart() {
|
||||||
|
return rvaStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes in the block (function)
|
||||||
|
* @return the number of bytes in the block
|
||||||
|
*/
|
||||||
|
public long getNumberBlockBytes() {
|
||||||
|
return numBlockBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes used by local variables
|
||||||
|
* @return the number of bytes used by locals
|
||||||
|
*/
|
||||||
|
public long getNumberLocalBytes() {
|
||||||
|
return numLocalBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes used by the parameters
|
||||||
|
* @return the number of bytes used by parameters
|
||||||
|
*/
|
||||||
|
public long getNumberParameterBytes() {
|
||||||
|
return numParamBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max number of stack bytes
|
||||||
|
* @return max stack bytes
|
||||||
|
*/
|
||||||
|
public long getMaxStackBytes() {
|
||||||
|
return maxStackBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: change javadoc and method name and underlying variable once we've determined what
|
||||||
|
// this is
|
||||||
|
/**
|
||||||
|
* Returns the frame func... not yet sure what this is
|
||||||
|
* @return the frame func
|
||||||
|
*/
|
||||||
|
public long getFrameFunc() {
|
||||||
|
return frameFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes in the function prolog
|
||||||
|
* @return the number of bytes in the prolog
|
||||||
|
*/
|
||||||
|
public int getNumberFunctionPrologBytes() {
|
||||||
|
return numPrologBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes for saved registers
|
||||||
|
* @return the number of bytes used by saved registers
|
||||||
|
*/
|
||||||
|
public int getNumberSavedRegisterBytes() {
|
||||||
|
return numSavedRegBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether has SEH
|
||||||
|
* @return {@code true} if has SEH
|
||||||
|
*/
|
||||||
|
public boolean hasSEH() {
|
||||||
|
return hasSEH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether has EH
|
||||||
|
* @return {@code true} if has EH
|
||||||
|
*/
|
||||||
|
public boolean hasEH() {
|
||||||
|
return hasEH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether is function start
|
||||||
|
* @return {@code true} if us function start
|
||||||
|
*/
|
||||||
|
public boolean isFunctionStart() {
|
||||||
|
return isFunctionStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the reserved, remaining 29 bit-field bits
|
||||||
|
* @return the value of the reserved field
|
||||||
|
*/
|
||||||
|
public long reserved() {
|
||||||
|
return reserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(PdbByteReader reader) throws PdbException {
|
||||||
|
if (reader.numRemaining() < 32) {
|
||||||
|
throw new PdbException("Not enough data for FrameDataRecord");
|
||||||
|
}
|
||||||
|
rvaStart = reader.parseUnsignedIntVal();
|
||||||
|
numBlockBytes = reader.parseUnsignedIntVal();
|
||||||
|
numLocalBytes = reader.parseUnsignedIntVal();
|
||||||
|
numParamBytes = reader.parseUnsignedIntVal();
|
||||||
|
maxStackBytes = reader.parseUnsignedIntVal();
|
||||||
|
frameFunc = reader.parseUnsignedIntVal();
|
||||||
|
numPrologBytes = reader.parseUnsignedShortVal();
|
||||||
|
numSavedRegBytes = reader.parseUnsignedShortVal();
|
||||||
|
reserved = reader.parseUnsignedIntVal();
|
||||||
|
hasSEH = (reserved & 0x01) == 0x01;
|
||||||
|
reserved >>= 1;
|
||||||
|
hasEH = (reserved & 0x01) == 0x01;
|
||||||
|
reserved >>= 1;
|
||||||
|
isFunctionStart = (reserved & 0x01) == 0x01;
|
||||||
|
reserved >>= 1;
|
||||||
|
reserved &= 0x01ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps the {@link FramePointerOmissionRecord}. This package-protected method is for
|
||||||
|
* debugging only.
|
||||||
|
* @param writer {@link Writer} to which to write the debug dump.
|
||||||
|
* @throws IOException On issue writing to the {@link Writer}.
|
||||||
|
*/
|
||||||
|
void dump(Writer writer) throws IOException {
|
||||||
|
writer.write("FrameDataRecord---------------------------------------------\n");
|
||||||
|
writer.write(String.format("rvaStart: 0X%08X\n", rvaStart));
|
||||||
|
writer.write(String.format("numBlockBytes: 0X%08X\n", numBlockBytes));
|
||||||
|
writer.write(String.format("numLocalBytes: 0X%08X\n", numLocalBytes));
|
||||||
|
writer.write(String.format("numParamBytes: 0X%08X\n", numParamBytes));
|
||||||
|
writer.write(String.format("maxStackBytes: 0X%08X\n", maxStackBytes));
|
||||||
|
writer.write(String.format("frameFunc: 0X%08X\n", frameFunc));
|
||||||
|
writer.write(String.format("numPrologBytes: 0X%04X\n", numPrologBytes));
|
||||||
|
writer.write(String.format("numSavedRegBytes: 0X%04X\n", numSavedRegBytes));
|
||||||
|
writer.write(
|
||||||
|
String.format("hasStructuedExceptionHandling: %s\n", Boolean.toString(hasSEH)));
|
||||||
|
writer.write(String.format("hasExceptionHandling: %s\n", Boolean.toString(hasEH)));
|
||||||
|
writer.write(String.format("isFunctionStart: %s\n", Boolean.toString(isFunctionStart)));
|
||||||
|
writer.write("End FrameDataRecord-----------------------------------------\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-2
@@ -198,8 +198,7 @@ public class FramePointerOmissionRecord {
|
|||||||
void dump(Writer writer) throws IOException {
|
void dump(Writer writer) throws IOException {
|
||||||
writer.write("FramePointerOmissionRecord----------------------------------\n");
|
writer.write("FramePointerOmissionRecord----------------------------------\n");
|
||||||
writer.write(String.format("firstFunctionByteOffset: 0X%08X\n", firstFunctionByteOffset));
|
writer.write(String.format("firstFunctionByteOffset: 0X%08X\n", firstFunctionByteOffset));
|
||||||
writer.write(String.format("firstFunctionByteOffset: 0X%08X\n", firstFunctionByteOffset));
|
writer.write(String.format("numFunctionBytes: 0X%08X\n", numFunctionBytes));
|
||||||
writer.write(String.format("numFunctionBytes: 0X%08XX\n", numFunctionBytes));
|
|
||||||
writer.write(String.format("numLocalVariables: 0X%08X\n", numLocalVariables));
|
writer.write(String.format("numLocalVariables: 0X%08X\n", numLocalVariables));
|
||||||
writer.write(String.format("sizeOfParametersInDwords: 0X%08X\n", sizeOfParametersInDwords));
|
writer.write(String.format("sizeOfParametersInDwords: 0X%08X\n", sizeOfParametersInDwords));
|
||||||
writer.write(String.format("numFunctionPrologBytes: 0X%04X\n", numFunctionPrologBytes));
|
writer.write(String.format("numFunctionPrologBytes: 0X%04X\n", numFunctionPrologBytes));
|
||||||
|
|||||||
Reference in New Issue
Block a user