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>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>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>. 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>
|
||||
|
@ -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>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>. 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>. 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>
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.dwarf4.next;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.cmd.comments.AppendCommentCmd;
|
||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
import ghidra.app.util.bin.format.dwarf4.*;
|
||||
|
@ -202,26 +203,26 @@ public class DWARFFunctionImporter {
|
|||
return;
|
||||
}
|
||||
|
||||
DWARFFunction function = new DWARFFunction(prog.getName(diea));
|
||||
function.namespace = function.dni.getParentNamespace(currentProgram);
|
||||
DWARFFunction dfunc = new DWARFFunction(prog.getName(diea));
|
||||
dfunc.namespace = dfunc.dni.getParentNamespace(currentProgram);
|
||||
|
||||
Number lowPC = diea.getLowPC(0);
|
||||
function.address = toAddr(lowPC);
|
||||
function.highAddress =
|
||||
dfunc.address = toAddr(lowPC);
|
||||
dfunc.highAddress =
|
||||
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) {
|
||||
// Msg.info(this, "Duplicate function defintion found for " + dni.getCategoryPath() +
|
||||
// " at " + function.address + " in DIE " + diea.getHexOffset() + ", skipping");
|
||||
markAllChildrenAsProcessed(diea.getHeadFragment());
|
||||
return;
|
||||
}
|
||||
functionsProcessed.put(function.address,
|
||||
function.dni.getNamespacePath() + " DIE: " + diea.getHexOffset());
|
||||
functionsProcessed.put(dfunc.address,
|
||||
dfunc.dni.getNamespacePath() + " DIE: " + diea.getHexOffset());
|
||||
|
||||
// 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
|
||||
DWARFLocation frameLoc = null;
|
||||
|
@ -229,9 +230,9 @@ public class DWARFFunctionImporter {
|
|||
List<DWARFLocation> frameBase = diea.getAsLocation(DWARFAttribute.DW_AT_frame_base);
|
||||
// get the framebase register, find where the frame is finally set
|
||||
// up.
|
||||
frameLoc = getTopLocation(frameBase, function.address.getOffset());
|
||||
frameLoc = getTopLocation(frameBase, dfunc.address.getOffset());
|
||||
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
|
||||
// then operated on.
|
||||
DIEAggregate typeRef = diea.getTypeRef();
|
||||
if (typeRef != null) {
|
||||
function.retval = new DWARFVariable();
|
||||
function.retval.type = dwarfDTM.getDataType(typeRef, dwarfDTM.getVoidType());
|
||||
}
|
||||
DataType formalReturnType = (typeRef != null)
|
||||
? dwarfDTM.getDataType(typeRef, DataType.DEFAULT)
|
||||
: 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(
|
||||
DWARFTag.DW_TAG_formal_parameter)) {
|
||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||
|
||||
DWARFVariable var = processVariable(childDIEA, function, null, -1);
|
||||
if (var != null) {
|
||||
function.params.add(var);
|
||||
Parameter formalParam = createFormalParameter(childDIEA);
|
||||
if (formalParam == null) {
|
||||
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();
|
||||
|
||||
processFuncChildren(diea, function);
|
||||
outputFunction(function, diea);
|
||||
processFuncChildren(diea, dfunc);
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
* as a child of the specified function (if not null).
|
||||
|
@ -349,6 +471,9 @@ public class DWARFFunctionImporter {
|
|||
|
||||
DWARFLocation topLocation = getTopLocation(locList, funcAddr);
|
||||
if (topLocation == null) {
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -368,12 +493,18 @@ public class DWARFFunctionImporter {
|
|||
catch (DWARFExpressionException | UnsupportedOperationException
|
||||
| IndexOutOfBoundsException ex) {
|
||||
importSummary.exprReadError++;
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (exprEvaluator.isDwarfStackValue()) {
|
||||
importSummary.varDWARFExpressionValue++;
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (exprEvaluator.useUnknownRegister() && exprEvaluator.isRegisterLocation()) {
|
||||
|
@ -386,6 +517,9 @@ public class DWARFFunctionImporter {
|
|||
}
|
||||
else if (exprEvaluator.useUnknownRegister()) {
|
||||
importSummary.varDynamicRegisterError++;
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (exprEvaluator.isStackRelative()) {
|
||||
|
@ -420,6 +554,9 @@ public class DWARFFunctionImporter {
|
|||
" can not fit into specified register " + dvar.reg.getName() +
|
||||
", size=" + dvar.reg.getMinimumByteSize() +
|
||||
", skipping. DWARF DIE: " + diea.getHexOffset());
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -430,6 +567,9 @@ public class DWARFFunctionImporter {
|
|||
// 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.
|
||||
importSummary.unknownRegistersEncountered.add(exprEvaluator.getRawLastRegister());
|
||||
if (dfunc != null) {
|
||||
dfunc.localVarErrors = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1030,75 +1170,7 @@ public class DWARFFunctionImporter {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void outputFunction(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) {
|
||||
private Function createFunction(DWARFFunction dfunc, DIEAggregate diea) {
|
||||
try {
|
||||
// create a new symbol if one does not exist (symbol table will figure this out)
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
|
@ -1129,6 +1201,30 @@ public class DWARFFunctionImporter {
|
|||
function = currentProgram.getFunctionManager().createFunction(null, dfunc.address,
|
||||
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;
|
||||
}
|
||||
catch (OverlappingFunctionException e) {
|
||||
|
@ -1152,14 +1248,14 @@ public class DWARFFunctionImporter {
|
|||
* @throws InvalidInputException invalid parameter name
|
||||
* @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 {
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
// Create a set containing all the unique parameter names determined so far so they can
|
||||
// be avoided as additional parameter names are determined.
|
||||
Set<String> namesSoFar = new HashSet<>();
|
||||
for (int ordinal = 0; ordinal < parameters.length; ordinal++) {
|
||||
Parameter parameter = parameters[ordinal];
|
||||
for (int ordinal = 0; ordinal < parameters.size(); ordinal++) {
|
||||
Parameter parameter = parameters.get(ordinal);
|
||||
String baseName = parameter.getName();
|
||||
if (ordinal == 0 && Function.THIS_PARAM_NAME.equals(baseName)) {
|
||||
continue;
|
||||
|
@ -1233,14 +1329,13 @@ public class DWARFFunctionImporter {
|
|||
}
|
||||
|
||||
private void commitPrototype(Function function, Variable returnVariable,
|
||||
ArrayList<Parameter> params, PrototypeModel protoModel)
|
||||
List<Parameter> params, PrototypeModel protoModel)
|
||||
throws InvalidInputException, DuplicateNameException {
|
||||
|
||||
Parameter[] paramarray = new Parameter[params.size()];
|
||||
params.toArray(paramarray);
|
||||
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
||||
|
||||
if (protoModel == null) {
|
||||
Parameter[] paramarray = params.toArray(Parameter[]::new);
|
||||
protoModel = compilerSpec.findBestCallingConvention(paramarray);
|
||||
}
|
||||
|
||||
|
@ -1249,7 +1344,7 @@ public class DWARFFunctionImporter {
|
|||
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
setUniqueParameterNames(function, paramarray);
|
||||
setUniqueParameterNames(function, params);
|
||||
function.updateFunction(protoModel.getName(), returnVariable, params,
|
||||
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED);
|
||||
}
|
||||
|
@ -1361,9 +1456,10 @@ public class DWARFFunctionImporter {
|
|||
public DWARFVariable retval;
|
||||
public boolean isExternal;
|
||||
public long frameBase;
|
||||
public ArrayList<DWARFVariable> params = new ArrayList<>();
|
||||
public ArrayList<DWARFVariable> local = new ArrayList<>();
|
||||
public List<DWARFVariable> params = new ArrayList<>();
|
||||
public List<DWARFVariable> local = new ArrayList<>();
|
||||
public boolean varArg;
|
||||
public boolean localVarErrors; // set to true if problem w/local var decoding
|
||||
|
||||
public DWARFFunction(DWARFNameInfo dni) {
|
||||
this.dni = dni;
|
||||
|
|
|
@ -461,8 +461,12 @@ public class DemangledFunction extends DemangledObject {
|
|||
// If returnType is null check for constructor or destructor names
|
||||
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
||||
String n = getName();
|
||||
if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) {
|
||||
// constructor && destructor
|
||||
if (n.equals(namespace.getName())) {
|
||||
// constructor
|
||||
return DataType.DEFAULT;
|
||||
}
|
||||
if (n.equals("~" + namespace.getName())) {
|
||||
// destructor
|
||||
return VoidDataType.dataType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,14 @@ public abstract class AbstractMemberFunctionMsType extends AbstractMsType {
|
|||
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.
|
||||
* @return The number of parameters.
|
||||
|
|
|
@ -58,4 +58,8 @@ public class FunctionMsAttributes extends AbstractParsableItem {
|
|||
isInstanceConstructorOfClassWithVirtualBases = ((attributes & 0x0001) == 0x0001);
|
||||
}
|
||||
|
||||
boolean isConstructor() {
|
||||
return isInstanceConstructor || isInstanceConstructorOfClassWithVirtualBases;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,6 +121,14 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier {
|
|||
*/
|
||||
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
|
||||
* convention, return type, and arguments list.
|
||||
|
@ -203,6 +211,10 @@ public abstract class AbstractFunctionTypeApplier extends MsTypeApplier {
|
|||
|
||||
private boolean setReturnType() {
|
||||
|
||||
if (isConstructor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DataType returnDataType = returnApplier.getDataType();
|
||||
if (returnDataType == null) {
|
||||
applicator.appendLogMsg("Return type is null in " + functionDefinition.getName());
|
||||
|
|
|
@ -75,6 +75,11 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier {
|
|||
return ((AbstractMemberFunctionMsType) msType).getArgListRecordNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConstructor() {
|
||||
return ((AbstractMemberFunctionMsType) msType).isConstructor();
|
||||
}
|
||||
|
||||
@Override
|
||||
void apply() throws PdbException, CancelledException {
|
||||
predefineClasses();
|
||||
|
@ -175,8 +180,7 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier {
|
|||
// }
|
||||
|
||||
private MsTypeApplier getThisPointerApplier(AbstractMemberFunctionMsType procType) {
|
||||
MsTypeApplier applier =
|
||||
applicator.getTypeApplier(procType.getThisPointerRecordNumber());
|
||||
MsTypeApplier applier = applicator.getTypeApplier(procType.getThisPointerRecordNumber());
|
||||
|
||||
// if ((applier instanceof PrimitiveTypeApplier &&
|
||||
// ((PrimitiveTypeApplier) applier).isNoType())) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue