mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
6a8788acbc
7 changed files with 235 additions and 103 deletions
|
@ -27,6 +27,9 @@
|
||||||
<li><I>Data Types</I>. Corrected segmented 32-bit pointer datatype address generation for 16:16 x86 far pointers. (GP-534, Issue #2548)</li>
|
<li><I>Data Types</I>. Corrected segmented 32-bit pointer datatype address generation for 16:16 x86 far pointers. (GP-534, Issue #2548)</li>
|
||||||
<li><I>Decompiler</I>. Fixed Decompiler issue where, when a function name extends beyond the line limit, an end-of-line comment could wrap around to additional lines without including additional <code>//</code> comment indicators. (GP-473)</li>
|
<li><I>Decompiler</I>. Fixed Decompiler issue where, when a function name extends beyond the line limit, an end-of-line comment could wrap around to additional lines without including additional <code>//</code> comment indicators. (GP-473)</li>
|
||||||
<li><I>Decompiler</I>. Corrected an exception that could occur when attempting to edit function signature from the Decompiler. (GP-597, Issue #2601)</li>
|
<li><I>Decompiler</I>. Corrected an exception that could occur when attempting to edit function signature from the Decompiler. (GP-597, Issue #2601)</li>
|
||||||
|
<li><I>Demangler</I>. Changed return type applied to constructors by Demangler from <code>void</code> to <code>Undefined</code>, allowing the Decompiler to determine the type. (GP-790)</li>
|
||||||
|
<li><I>DWARF</I>. Improved handling of empty DWARF compile units. (GP-743)</li>
|
||||||
|
<li><I>DWARF</I>. Improved handling of DWARF function signatures when parameter info contains unsupported location opcodes or failed to resolve datatypes. (GP-794)</li>
|
||||||
<li><I>Eclipse Integration</I>. When installing the SleighEditor into Eclipse, the plugin will now show up under the Ghidra category. Previously the <B>Group Items by Category</B> option had to be turned off before the SleighEditor would appear as a visible entry. (GP-564)</li>
|
<li><I>Eclipse Integration</I>. When installing the SleighEditor into Eclipse, the plugin will now show up under the Ghidra category. Previously the <B>Group Items by Category</B> option had to be turned off before the SleighEditor would appear as a visible entry. (GP-564)</li>
|
||||||
<li><I>Eclipse Integration</I>. Fixed an issue with Eclipse PyDev breakpoints not catching. (GP-668, Issue #2713)</li>
|
<li><I>Eclipse Integration</I>. Fixed an issue with Eclipse PyDev breakpoints not catching. (GP-668, Issue #2713)</li>
|
||||||
<li><I>Eclipse Integration</I>. Fixed an Eclipse GhidraDev exception that occurred when creating a new Ghidra scripting project if a <B>~/ghidra_scripts</B> directory did not exist. (GP-669)</li>
|
<li><I>Eclipse Integration</I>. Fixed an Eclipse GhidraDev exception that occurred when creating a new Ghidra scripting project if a <B>~/ghidra_scripts</B> directory did not exist. (GP-669)</li>
|
||||||
|
@ -44,6 +47,7 @@
|
||||||
<li><I>Importer:Mach-O</I>. Fixed an exception that occurred when importing Mach-O files that define zero <code>LC_BUILD_VERSION</code> tool entries. (GP-702, Issue #2192)</li>
|
<li><I>Importer:Mach-O</I>. Fixed an exception that occurred when importing Mach-O files that define zero <code>LC_BUILD_VERSION</code> tool entries. (GP-702, Issue #2192)</li>
|
||||||
<li><I>PDB</I>. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)</li>
|
<li><I>PDB</I>. Fixed createPdbXmlFiles.bat to permit spaces in the path name of Ghidra installation folder and the batch argument name. (GP-575, Issue #2167)</li>
|
||||||
<li><I>PDB</I>. Fixed PDB Universal analyzer to set the run-once flag when finished. (GP-724)</li>
|
<li><I>PDB</I>. Fixed PDB Universal analyzer to set the run-once flag when finished. (GP-724)</li>
|
||||||
|
<li><I>PDB</I>. Changed return type applied to constructors by PDB Universal from <code>void</code> to <code>Undefined</code>, allowing the Decompiler to determine the type. (GP-791)</li>
|
||||||
<li><I>Processors</I>. Added missing <code>RFE</code> instruction in MIPS up to version R3000. (GP-33, Issue #1766)</li>
|
<li><I>Processors</I>. Added missing <code>RFE</code> instruction in MIPS up to version R3000. (GP-33, Issue #1766)</li>
|
||||||
<li><I>Processors</I>. ARM instruction <code>VMUL</code> now decodes correctly. (GP-627, Issue #2677)</li>
|
<li><I>Processors</I>. ARM instruction <code>VMUL</code> now decodes correctly. (GP-627, Issue #2677)</li>
|
||||||
<li><I>Processors</I>. Added missing <code>CFINV</code> instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)</li>
|
<li><I>Processors</I>. Added missing <code>CFINV</code> instruction to AARCH64 processor specification and added definitions for locals in neon instructions. (GP-655, Issue #2710)</li>
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.dwarf4.next;
|
package ghidra.app.util.bin.format.dwarf4.next;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.cmd.comments.AppendCommentCmd;
|
import ghidra.app.cmd.comments.AppendCommentCmd;
|
||||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||||
import ghidra.app.util.bin.format.dwarf4.*;
|
import ghidra.app.util.bin.format.dwarf4.*;
|
||||||
|
@ -202,26 +203,26 @@ public class DWARFFunctionImporter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFFunction function = new DWARFFunction(prog.getName(diea));
|
DWARFFunction dfunc = new DWARFFunction(prog.getName(diea));
|
||||||
function.namespace = function.dni.getParentNamespace(currentProgram);
|
dfunc.namespace = dfunc.dni.getParentNamespace(currentProgram);
|
||||||
|
|
||||||
Number lowPC = diea.getLowPC(0);
|
Number lowPC = diea.getLowPC(0);
|
||||||
function.address = toAddr(lowPC);
|
dfunc.address = toAddr(lowPC);
|
||||||
function.highAddress =
|
dfunc.highAddress =
|
||||||
diea.hasAttribute(DWARFAttribute.DW_AT_high_pc) ? toAddr(diea.getHighPC()) : null;
|
diea.hasAttribute(DWARFAttribute.DW_AT_high_pc) ? toAddr(diea.getHighPC()) : null;
|
||||||
|
|
||||||
String previousFunctionProcessed = functionsProcessed.get(function.address);
|
String previousFunctionProcessed = functionsProcessed.get(dfunc.address);
|
||||||
if (previousFunctionProcessed != null) {
|
if (previousFunctionProcessed != null) {
|
||||||
// Msg.info(this, "Duplicate function defintion found for " + dni.getCategoryPath() +
|
// Msg.info(this, "Duplicate function defintion found for " + dni.getCategoryPath() +
|
||||||
// " at " + function.address + " in DIE " + diea.getHexOffset() + ", skipping");
|
// " at " + function.address + " in DIE " + diea.getHexOffset() + ", skipping");
|
||||||
markAllChildrenAsProcessed(diea.getHeadFragment());
|
markAllChildrenAsProcessed(diea.getHeadFragment());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
functionsProcessed.put(function.address,
|
functionsProcessed.put(dfunc.address,
|
||||||
function.dni.getNamespacePath() + " DIE: " + diea.getHexOffset());
|
dfunc.dni.getNamespacePath() + " DIE: " + diea.getHexOffset());
|
||||||
|
|
||||||
// Check if the function is an external function
|
// Check if the function is an external function
|
||||||
function.isExternal = diea.getBool(DWARFAttribute.DW_AT_external, false);
|
dfunc.isExternal = diea.getBool(DWARFAttribute.DW_AT_external, false);
|
||||||
|
|
||||||
// Retrieve the frame base if it exists
|
// Retrieve the frame base if it exists
|
||||||
DWARFLocation frameLoc = null;
|
DWARFLocation frameLoc = null;
|
||||||
|
@ -229,9 +230,9 @@ public class DWARFFunctionImporter {
|
||||||
List<DWARFLocation> frameBase = diea.getAsLocation(DWARFAttribute.DW_AT_frame_base);
|
List<DWARFLocation> frameBase = diea.getAsLocation(DWARFAttribute.DW_AT_frame_base);
|
||||||
// get the framebase register, find where the frame is finally set
|
// get the framebase register, find where the frame is finally set
|
||||||
// up.
|
// up.
|
||||||
frameLoc = getTopLocation(frameBase, function.address.getOffset());
|
frameLoc = getTopLocation(frameBase, dfunc.address.getOffset());
|
||||||
if (frameLoc != null) {
|
if (frameLoc != null) {
|
||||||
function.frameBase = (int) diea.evaluateLocation(frameLoc);
|
dfunc.frameBase = (int) diea.evaluateLocation(frameLoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,26 +246,134 @@ public class DWARFFunctionImporter {
|
||||||
// function passing a pointer to the callee function where the object is
|
// function passing a pointer to the callee function where the object is
|
||||||
// then operated on.
|
// then operated on.
|
||||||
DIEAggregate typeRef = diea.getTypeRef();
|
DIEAggregate typeRef = diea.getTypeRef();
|
||||||
if (typeRef != null) {
|
DataType formalReturnType = (typeRef != null)
|
||||||
function.retval = new DWARFVariable();
|
? dwarfDTM.getDataType(typeRef, DataType.DEFAULT)
|
||||||
function.retval.type = dwarfDTM.getDataType(typeRef, dwarfDTM.getVoidType());
|
: dwarfDTM.getVoidType();
|
||||||
}
|
dfunc.retval = new DWARFVariable();
|
||||||
|
dfunc.retval.type = formalReturnType;
|
||||||
|
|
||||||
|
boolean formalParamsOnly = false;
|
||||||
|
boolean skipFuncSignature = false;
|
||||||
|
List<Parameter> formalParams = new ArrayList<>();
|
||||||
|
|
||||||
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(
|
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(
|
||||||
DWARFTag.DW_TAG_formal_parameter)) {
|
DWARFTag.DW_TAG_formal_parameter)) {
|
||||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||||
|
|
||||||
DWARFVariable var = processVariable(childDIEA, function, null, -1);
|
Parameter formalParam = createFormalParameter(childDIEA);
|
||||||
if (var != null) {
|
if (formalParam == null) {
|
||||||
function.params.add(var);
|
skipFuncSignature = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
formalParams.add(formalParam);
|
||||||
|
|
||||||
|
if (!formalParamsOnly) {
|
||||||
|
DWARFVariable var = processVariable(childDIEA, dfunc, null, -1);
|
||||||
|
if (var == null) {
|
||||||
|
// we had an error, can't rely on detailed param data, fallback to
|
||||||
|
// formal params
|
||||||
|
formalParamsOnly = true;
|
||||||
|
dfunc.params.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dfunc.params.add(var);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function.varArg =
|
dfunc.varArg =
|
||||||
!diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_unspecified_parameters).isEmpty();
|
!diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_unspecified_parameters).isEmpty();
|
||||||
|
|
||||||
processFuncChildren(diea, function);
|
processFuncChildren(diea, dfunc);
|
||||||
outputFunction(function, diea);
|
|
||||||
|
|
||||||
|
Function gfunc = createFunction(dfunc, diea);
|
||||||
|
if (gfunc != null) {
|
||||||
|
|
||||||
|
if (formalParams.isEmpty() && dfunc.localVarErrors) {
|
||||||
|
// if there were no defined parameters and we had problems decoding local variables,
|
||||||
|
// don't force the method to have an empty param signature because there are other
|
||||||
|
// issues afoot.
|
||||||
|
skipFuncSignature = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipFuncSignature) {
|
||||||
|
Msg.error(this,
|
||||||
|
"Failed to get function signature information, leaving undefined: " +
|
||||||
|
gfunc.getName() + "@" + gfunc.getEntryPoint());
|
||||||
|
Msg.debug(this, "DIE info: " + diea.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formalParamsOnly) {
|
||||||
|
updateFunctionSignatureWithFormalParams(gfunc, formalParams,
|
||||||
|
formalReturnType, dfunc.varArg, diea);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateFunctionSignatureWithDetailParams(gfunc, dfunc, diea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFunctionSignatureWithFormalParams(Function gfunc, List<Parameter> params,
|
||||||
|
DataType returnType, boolean varArgs, DIEAggregate diea) {
|
||||||
|
try {
|
||||||
|
ReturnParameterImpl returnVar = new ReturnParameterImpl(returnType, currentProgram);
|
||||||
|
try {
|
||||||
|
gfunc.setVarArgs(varArgs);
|
||||||
|
gfunc.updateFunction(null, returnVar, params,
|
||||||
|
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||||
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
|
// try again after adjusting param names
|
||||||
|
setUniqueParameterNames(gfunc, params);
|
||||||
|
gfunc.updateFunction(null, returnVar, params,
|
||||||
|
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidInputException | DuplicateNameException e) {
|
||||||
|
Msg.error(this,
|
||||||
|
"Error updating function " + gfunc.getName() + " with formal params at " +
|
||||||
|
gfunc.getEntryPoint().toString() + ": " + e.getMessage());
|
||||||
|
Msg.error(this, "DIE info: " + diea.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFunctionSignatureWithDetailParams(Function gfunc, DWARFFunction dfunc,
|
||||||
|
DIEAggregate diea) {
|
||||||
|
try {
|
||||||
|
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
||||||
|
PrototypeModel convention = null;
|
||||||
|
Variable returnVariable;
|
||||||
|
List<Parameter> params = new ArrayList<>();
|
||||||
|
|
||||||
|
returnVariable = buildReturnVariable(dfunc.retval);
|
||||||
|
for (int i = 0; i < dfunc.params.size(); ++i) {
|
||||||
|
Parameter curparam = buildParameter(gfunc, i, dfunc.params.get(i), diea);
|
||||||
|
params.add(curparam);
|
||||||
|
if (i == 0 && checkThisParameter(dfunc.params.get(0), diea)) {
|
||||||
|
convention = compilerSpec.matchConvention(GenericCallingConvention.thiscall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dfunc.local.size(); ++i) {
|
||||||
|
commitLocal(gfunc, dfunc.local.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfunc.retval != null || params.size() > 0) {
|
||||||
|
// Add the function signature definition into the data type manager
|
||||||
|
// TODO: createFunctionDefinition(dfunc, infopath);
|
||||||
|
|
||||||
|
// NOTE: Storage is computed above for the purpose of identifying
|
||||||
|
// a best fit calling convention. The commitPrototype method currently
|
||||||
|
// always employs dynamic storage.
|
||||||
|
commitPrototype(gfunc, returnVariable, params, convention);
|
||||||
|
gfunc.setVarArgs(dfunc.varArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidInputException | DuplicateNameException iie) {
|
||||||
|
Msg.error(this, "Error updating function " + dfunc.dni.getName() + " at " +
|
||||||
|
dfunc.address.toString() + ": " + iie.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processFuncChildren(DIEAggregate diea, DWARFFunction dfunc)
|
private void processFuncChildren(DIEAggregate diea, DWARFFunction dfunc)
|
||||||
|
@ -305,6 +414,19 @@ public class DWARFFunctionImporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Parameter createFormalParameter(DIEAggregate diea) {
|
||||||
|
String name = diea.getString(DWARFAttribute.DW_AT_name, null);
|
||||||
|
DataType dt = dwarfDTM.getDataType(diea.getTypeRef(), dwarfDTM.getVoidType());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new ParameterImpl(name, dt, currentProgram);
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
Msg.debug(this, "Failed to create parameter for " + diea.toString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link DWARFVariable} from the specified {@link DIEAggregate DIEA} and
|
* Creates a new {@link DWARFVariable} from the specified {@link DIEAggregate DIEA} and
|
||||||
* as a child of the specified function (if not null).
|
* as a child of the specified function (if not null).
|
||||||
|
@ -349,6 +471,9 @@ public class DWARFFunctionImporter {
|
||||||
|
|
||||||
DWARFLocation topLocation = getTopLocation(locList, funcAddr);
|
DWARFLocation topLocation = getTopLocation(locList, funcAddr);
|
||||||
if (topLocation == null) {
|
if (topLocation == null) {
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,12 +493,18 @@ public class DWARFFunctionImporter {
|
||||||
catch (DWARFExpressionException | UnsupportedOperationException
|
catch (DWARFExpressionException | UnsupportedOperationException
|
||||||
| IndexOutOfBoundsException ex) {
|
| IndexOutOfBoundsException ex) {
|
||||||
importSummary.exprReadError++;
|
importSummary.exprReadError++;
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exprEvaluator.isDwarfStackValue()) {
|
if (exprEvaluator.isDwarfStackValue()) {
|
||||||
importSummary.varDWARFExpressionValue++;
|
importSummary.varDWARFExpressionValue++;
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (exprEvaluator.useUnknownRegister() && exprEvaluator.isRegisterLocation()) {
|
else if (exprEvaluator.useUnknownRegister() && exprEvaluator.isRegisterLocation()) {
|
||||||
|
@ -386,6 +517,9 @@ public class DWARFFunctionImporter {
|
||||||
}
|
}
|
||||||
else if (exprEvaluator.useUnknownRegister()) {
|
else if (exprEvaluator.useUnknownRegister()) {
|
||||||
importSummary.varDynamicRegisterError++;
|
importSummary.varDynamicRegisterError++;
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (exprEvaluator.isStackRelative()) {
|
else if (exprEvaluator.isStackRelative()) {
|
||||||
|
@ -420,6 +554,9 @@ public class DWARFFunctionImporter {
|
||||||
" can not fit into specified register " + dvar.reg.getName() +
|
" can not fit into specified register " + dvar.reg.getName() +
|
||||||
", size=" + dvar.reg.getMinimumByteSize() +
|
", size=" + dvar.reg.getMinimumByteSize() +
|
||||||
", skipping. DWARF DIE: " + diea.getHexOffset());
|
", skipping. DWARF DIE: " + diea.getHexOffset());
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +567,9 @@ public class DWARFFunctionImporter {
|
||||||
// The DWARF register did not have a mapping to a Ghidra register, so
|
// The DWARF register did not have a mapping to a Ghidra register, so
|
||||||
// log it to be displayed in an error summary at end of import phase.
|
// log it to be displayed in an error summary at end of import phase.
|
||||||
importSummary.unknownRegistersEncountered.add(exprEvaluator.getRawLastRegister());
|
importSummary.unknownRegistersEncountered.add(exprEvaluator.getRawLastRegister());
|
||||||
|
if (dfunc != null) {
|
||||||
|
dfunc.localVarErrors = true;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1030,75 +1170,7 @@ public class DWARFFunctionImporter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputFunction(DWARFFunction dfunc, DIEAggregate diea) {
|
private Function createFunction(DWARFFunction dfunc, DIEAggregate diea) {
|
||||||
try {
|
|
||||||
Function function = createFunction(dfunc);
|
|
||||||
if (function == null) {
|
|
||||||
Msg.error(this, "DWARF DIE: " + diea.getHexOffset());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWARFSourceInfo sourceInfo = DWARFSourceInfo.create(diea);
|
|
||||||
if (sourceInfo != null) {
|
|
||||||
// Move the function into the program tree of the file
|
|
||||||
moveIntoFragment(function.getName(), dfunc.address,
|
|
||||||
dfunc.highAddress != null ? dfunc.highAddress : dfunc.address.add(1),
|
|
||||||
sourceInfo.getFilename());
|
|
||||||
|
|
||||||
if (importOptions.isOutputSourceLocationInfo()) {
|
|
||||||
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
|
||||||
sourceInfo.getDescriptionStr(), "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (importOptions.isOutputDIEInfo()) {
|
|
||||||
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
|
||||||
"DWARF DIE: " + diea.getHexOffset(), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
DWARFNameInfo dni = prog.getName(diea);
|
|
||||||
if (dni.isNameModified()) {
|
|
||||||
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
|
||||||
"Original name: " + dni.getOriginalName(), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
|
||||||
PrototypeModel convention = null;
|
|
||||||
Variable returnVariable;
|
|
||||||
ArrayList<Parameter> params = new ArrayList<>();
|
|
||||||
|
|
||||||
// boolean specifyStorage = evaluateParameterStorage(dfunc);
|
|
||||||
|
|
||||||
returnVariable = buildReturnVariable(dfunc.retval);
|
|
||||||
for (int i = 0; i < dfunc.params.size(); ++i) {
|
|
||||||
Parameter curparam = buildParameter(function, i, dfunc.params.get(i), diea);
|
|
||||||
params.add(curparam);
|
|
||||||
if (i == 0 && checkThisParameter(dfunc.params.get(0), diea)) {
|
|
||||||
convention = compilerSpec.matchConvention(GenericCallingConvention.thiscall);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < dfunc.local.size(); ++i) {
|
|
||||||
commitLocal(function, dfunc.local.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dfunc.retval != null || params.size() > 0) {
|
|
||||||
// Add the function signature definition into the data type manager
|
|
||||||
// TODO: createFunctionDefinition(dfunc, infopath);
|
|
||||||
|
|
||||||
// NOTE: Storage is computed above for the purpose of identifying
|
|
||||||
// a best fit calling convention. The commitPrototype method currently
|
|
||||||
// always employs dynamic storage.
|
|
||||||
commitPrototype(function, returnVariable, params, convention);
|
|
||||||
function.setVarArgs(dfunc.varArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (InvalidInputException | DuplicateNameException iie) {
|
|
||||||
Msg.error(this, "Error updating function " + dfunc.dni.getName() + " at " +
|
|
||||||
dfunc.address.toString() + ": " + iie.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Function createFunction(DWARFFunction dfunc) {
|
|
||||||
try {
|
try {
|
||||||
// create a new symbol if one does not exist (symbol table will figure this out)
|
// create a new symbol if one does not exist (symbol table will figure this out)
|
||||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||||
|
@ -1129,6 +1201,30 @@ public class DWARFFunctionImporter {
|
||||||
function = currentProgram.getFunctionManager().createFunction(null, dfunc.address,
|
function = currentProgram.getFunctionManager().createFunction(null, dfunc.address,
|
||||||
new AddressSet(dfunc.address), SourceType.IMPORTED);
|
new AddressSet(dfunc.address), SourceType.IMPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWARFSourceInfo sourceInfo = DWARFSourceInfo.create(diea);
|
||||||
|
if (sourceInfo != null) {
|
||||||
|
// Move the function into the program tree of the file
|
||||||
|
moveIntoFragment(function.getName(), dfunc.address,
|
||||||
|
dfunc.highAddress != null ? dfunc.highAddress : dfunc.address.add(1),
|
||||||
|
sourceInfo.getFilename());
|
||||||
|
|
||||||
|
if (importOptions.isOutputSourceLocationInfo()) {
|
||||||
|
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
||||||
|
sourceInfo.getDescriptionStr(), "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (importOptions.isOutputDIEInfo()) {
|
||||||
|
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
||||||
|
"DWARF DIE: " + diea.getHexOffset(), "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
DWARFNameInfo dni = prog.getName(diea);
|
||||||
|
if (dni.isNameModified()) {
|
||||||
|
appendComment(dfunc.address, CodeUnit.PLATE_COMMENT,
|
||||||
|
"Original name: " + dni.getOriginalName(), "\n");
|
||||||
|
}
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
catch (OverlappingFunctionException e) {
|
catch (OverlappingFunctionException e) {
|
||||||
|
@ -1152,14 +1248,14 @@ public class DWARFFunctionImporter {
|
||||||
* @throws InvalidInputException invalid parameter name
|
* @throws InvalidInputException invalid parameter name
|
||||||
* @throws DuplicateNameException (should not occur on non-DB parameter)
|
* @throws DuplicateNameException (should not occur on non-DB parameter)
|
||||||
*/
|
*/
|
||||||
private void setUniqueParameterNames(Function function, Parameter[] parameters)
|
private void setUniqueParameterNames(Function function, List<Parameter> parameters)
|
||||||
throws DuplicateNameException, InvalidInputException {
|
throws DuplicateNameException, InvalidInputException {
|
||||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||||
// Create a set containing all the unique parameter names determined so far so they can
|
// Create a set containing all the unique parameter names determined so far so they can
|
||||||
// be avoided as additional parameter names are determined.
|
// be avoided as additional parameter names are determined.
|
||||||
Set<String> namesSoFar = new HashSet<>();
|
Set<String> namesSoFar = new HashSet<>();
|
||||||
for (int ordinal = 0; ordinal < parameters.length; ordinal++) {
|
for (int ordinal = 0; ordinal < parameters.size(); ordinal++) {
|
||||||
Parameter parameter = parameters[ordinal];
|
Parameter parameter = parameters.get(ordinal);
|
||||||
String baseName = parameter.getName();
|
String baseName = parameter.getName();
|
||||||
if (ordinal == 0 && Function.THIS_PARAM_NAME.equals(baseName)) {
|
if (ordinal == 0 && Function.THIS_PARAM_NAME.equals(baseName)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1233,14 +1329,13 @@ public class DWARFFunctionImporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commitPrototype(Function function, Variable returnVariable,
|
private void commitPrototype(Function function, Variable returnVariable,
|
||||||
ArrayList<Parameter> params, PrototypeModel protoModel)
|
List<Parameter> params, PrototypeModel protoModel)
|
||||||
throws InvalidInputException, DuplicateNameException {
|
throws InvalidInputException, DuplicateNameException {
|
||||||
|
|
||||||
Parameter[] paramarray = new Parameter[params.size()];
|
|
||||||
params.toArray(paramarray);
|
|
||||||
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
||||||
|
|
||||||
if (protoModel == null) {
|
if (protoModel == null) {
|
||||||
|
Parameter[] paramarray = params.toArray(Parameter[]::new);
|
||||||
protoModel = compilerSpec.findBestCallingConvention(paramarray);
|
protoModel = compilerSpec.findBestCallingConvention(paramarray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1249,7 +1344,7 @@ public class DWARFFunctionImporter {
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
setUniqueParameterNames(function, paramarray);
|
setUniqueParameterNames(function, params);
|
||||||
function.updateFunction(protoModel.getName(), returnVariable, params,
|
function.updateFunction(protoModel.getName(), returnVariable, params,
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||||
}
|
}
|
||||||
|
@ -1361,9 +1456,10 @@ public class DWARFFunctionImporter {
|
||||||
public DWARFVariable retval;
|
public DWARFVariable retval;
|
||||||
public boolean isExternal;
|
public boolean isExternal;
|
||||||
public long frameBase;
|
public long frameBase;
|
||||||
public ArrayList<DWARFVariable> params = new ArrayList<>();
|
public List<DWARFVariable> params = new ArrayList<>();
|
||||||
public ArrayList<DWARFVariable> local = new ArrayList<>();
|
public List<DWARFVariable> local = new ArrayList<>();
|
||||||
public boolean varArg;
|
public boolean varArg;
|
||||||
|
public boolean localVarErrors; // set to true if problem w/local var decoding
|
||||||
|
|
||||||
public DWARFFunction(DWARFNameInfo dni) {
|
public DWARFFunction(DWARFNameInfo dni) {
|
||||||
this.dni = dni;
|
this.dni = dni;
|
||||||
|
|
|
@ -461,8 +461,12 @@ public class DemangledFunction extends DemangledObject {
|
||||||
// If returnType is null check for constructor or destructor names
|
// If returnType is null check for constructor or destructor names
|
||||||
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
||||||
String n = getName();
|
String n = getName();
|
||||||
if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) {
|
if (n.equals(namespace.getName())) {
|
||||||
// constructor && destructor
|
// constructor
|
||||||
|
return DataType.DEFAULT;
|
||||||
|
}
|
||||||
|
if (n.equals("~" + namespace.getName())) {
|
||||||
|
// destructor
|
||||||
return VoidDataType.dataType;
|
return VoidDataType.dataType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,14 @@ public abstract class AbstractMemberFunctionMsType extends AbstractMsType {
|
||||||
return functionAttributes;
|
return functionAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if known to be a constructor.
|
||||||
|
* @return true if constructor.
|
||||||
|
*/
|
||||||
|
public boolean isConstructor() {
|
||||||
|
return functionAttributes.isConstructor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of parameters to the function.
|
* Returns the number of parameters to the function.
|
||||||
* @return The number of parameters.
|
* @return The number of parameters.
|
||||||
|
|
|
@ -58,4 +58,8 @@ public class FunctionMsAttributes extends AbstractParsableItem {
|
||||||
isInstanceConstructorOfClassWithVirtualBases = ((attributes & 0x0001) == 0x0001);
|
isInstanceConstructorOfClassWithVirtualBases = ((attributes & 0x0001) == 0x0001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isConstructor() {
|
||||||
|
return isInstanceConstructor || isInstanceConstructorOfClassWithVirtualBases;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,14 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier {
|
||||||
*/
|
*/
|
||||||
protected abstract RecordNumber getArgListRecordNumber();
|
protected abstract RecordNumber getArgListRecordNumber();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if known to be a constructor.
|
||||||
|
* @return true if constructor.
|
||||||
|
*/
|
||||||
|
protected boolean isConstructor() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create the {@link DataType} based upon the type indices of the calling
|
* Method to create the {@link DataType} based upon the type indices of the calling
|
||||||
* convention, return type, and arguments list.
|
* convention, return type, and arguments list.
|
||||||
|
@ -203,6 +211,10 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier {
|
||||||
|
|
||||||
private boolean setReturnType() {
|
private boolean setReturnType() {
|
||||||
|
|
||||||
|
if (isConstructor()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DataType returnDataType = returnApplier.getDataType();
|
DataType returnDataType = returnApplier.getDataType();
|
||||||
if (returnDataType == null) {
|
if (returnDataType == null) {
|
||||||
applicator.appendLogMsg("Return type is null in " + functionDefinition.getName());
|
applicator.appendLogMsg("Return type is null in " + functionDefinition.getName());
|
||||||
|
|
|
@ -75,6 +75,11 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier {
|
||||||
return ((AbstractMemberFunctionMsType) msType).getArgListRecordNumber();
|
return ((AbstractMemberFunctionMsType) msType).getArgListRecordNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isConstructor() {
|
||||||
|
return ((AbstractMemberFunctionMsType) msType).isConstructor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void apply() throws PdbException, CancelledException {
|
void apply() throws PdbException, CancelledException {
|
||||||
predefineClasses();
|
predefineClasses();
|
||||||
|
@ -175,8 +180,7 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private MsTypeApplier getThisPointerApplier(AbstractMemberFunctionMsType procType) {
|
private MsTypeApplier getThisPointerApplier(AbstractMemberFunctionMsType procType) {
|
||||||
MsTypeApplier applier =
|
MsTypeApplier applier = applicator.getTypeApplier(procType.getThisPointerRecordNumber());
|
||||||
applicator.getTypeApplier(procType.getThisPointerRecordNumber());
|
|
||||||
|
|
||||||
// if ((applier instanceof PrimitiveTypeApplier &&
|
// if ((applier instanceof PrimitiveTypeApplier &&
|
||||||
// ((PrimitiveTypeApplier) applier).isNoType())) {
|
// ((PrimitiveTypeApplier) applier).isNoType())) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue