mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-3649 - DemangledObjects - separate lref/rref from pointerLeverls; fix MDMang function pointers indirection
This commit is contained in:
parent
edc6c52094
commit
9f5cfa5170
6 changed files with 153 additions and 63 deletions
|
@ -227,13 +227,21 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
|
|
||||||
StringBuilder typeBuffer = new StringBuilder();
|
StringBuilder typeBuffer = new StringBuilder();
|
||||||
int pointerLevels = getPointerLevels();
|
int pointerLevels = getPointerLevels();
|
||||||
if (pointerLevels > 0) {
|
if (pointerLevels > 0 || isReference() || isRValueReference()) {
|
||||||
|
|
||||||
addParentName(typeBuffer);
|
addParentName(typeBuffer);
|
||||||
|
|
||||||
for (int i = 0; i < pointerLevels; ++i) {
|
for (int i = 0; i < pointerLevels; ++i) {
|
||||||
typeBuffer.append(getTypeString());
|
typeBuffer.append(getTypeString());
|
||||||
}
|
}
|
||||||
|
// kludge for now... current type-emitting mechanism in DemangledObject hierarchy
|
||||||
|
// lacks a lot... needs revamped.
|
||||||
|
if (isLValueReference()) {
|
||||||
|
typeBuffer.append(" &");
|
||||||
|
}
|
||||||
|
else if (isRValueReference()) {
|
||||||
|
typeBuffer.append(" &&");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils.isBlank(typeBuffer)) {
|
if (!StringUtils.isBlank(typeBuffer)) {
|
||||||
|
@ -331,7 +339,25 @@ public abstract class AbstractDemangledFunctionDefinitionDataType extends Demang
|
||||||
dt = fddt;
|
dt = fddt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PointerDataType(dt, dataTypeManager);
|
// This was also totally wonked in terms of type-emitting. Whole mangled type needs
|
||||||
|
// gone through and revamped; not sure it is good to have pointer levels or reference
|
||||||
|
// information in a FunctionPointer... need to investigate more.
|
||||||
|
int numPointers = getPointerLevels();
|
||||||
|
|
||||||
|
for (int i = 0; i < numPointers; ++i) {
|
||||||
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLValueReference()) {
|
||||||
|
// Placeholder in prep for more lref work
|
||||||
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
|
}
|
||||||
|
else if (isRValueReference()) {
|
||||||
|
// Placeholder in prep for more rref work
|
||||||
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setParameters(FunctionDefinitionDataType fddt, DataTypeManager dataTypeManager) {
|
private void setParameters(FunctionDefinitionDataType fddt, DataTypeManager dataTypeManager) {
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
|
|
||||||
public static final String ARR_NOTATION = "[]";
|
public static final String ARR_NOTATION = "[]";
|
||||||
public static final String REF_NOTATION = "&";
|
public static final String REF_NOTATION = "&";
|
||||||
|
public static final String RIGHT_REF_NOTATION = "&&";
|
||||||
public static final String PTR_NOTATION = "*";
|
public static final String PTR_NOTATION = "*";
|
||||||
|
|
||||||
public static final String VOLATILE = "volatile";
|
public static final String VOLATILE = "volatile";
|
||||||
|
@ -100,7 +101,10 @@ public class DemangledDataType extends DemangledType {
|
||||||
private boolean isComplex;
|
private boolean isComplex;
|
||||||
private boolean isEnum;
|
private boolean isEnum;
|
||||||
private boolean isPointer64;
|
private boolean isPointer64;
|
||||||
private boolean isReference;
|
// Cannot be both lref and rref. Prior to C++11, we only had reference (& operator).
|
||||||
|
// This is now distinguished as left-value reference (l-value reference or lref), and there
|
||||||
|
// is now an additional right-value reference (r-value reference or rref) with the && operator.
|
||||||
|
private boolean isLValueReference;
|
||||||
private boolean isRValueReference;
|
private boolean isRValueReference;
|
||||||
private boolean isSigned;
|
private boolean isSigned;
|
||||||
private boolean isStruct;
|
private boolean isStruct;
|
||||||
|
@ -208,13 +212,20 @@ public class DemangledDataType extends DemangledType {
|
||||||
}
|
}
|
||||||
|
|
||||||
int numPointers = getPointerLevels();
|
int numPointers = getPointerLevels();
|
||||||
if (isReference()) {
|
|
||||||
numPointers++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < numPointers; ++i) {
|
for (int i = 0; i < numPointers; ++i) {
|
||||||
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLValueReference()) {
|
||||||
|
// Placeholder in prep for more lref work
|
||||||
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
|
}
|
||||||
|
else if (isRValueReference()) {
|
||||||
|
// Placeholder in prep for more rref work
|
||||||
|
dt = PointerDataType.getPointer(dt, dataTypeManager);
|
||||||
|
}
|
||||||
|
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +474,13 @@ public class DemangledDataType extends DemangledType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReference() {
|
public void setReference() {
|
||||||
isReference = true;
|
setLValueReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLValueReference() {
|
||||||
|
isLValueReference = true;
|
||||||
|
// Cannot be both
|
||||||
|
isRValueReference = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,6 +488,8 @@ public class DemangledDataType extends DemangledType {
|
||||||
*/
|
*/
|
||||||
public void setRValueReference() {
|
public void setRValueReference() {
|
||||||
isRValueReference = true;
|
isRValueReference = true;
|
||||||
|
// Cannot be both
|
||||||
|
isLValueReference = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSigned() {
|
public void setSigned() {
|
||||||
|
@ -550,7 +569,15 @@ public class DemangledDataType extends DemangledType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isReference() {
|
public boolean isReference() {
|
||||||
return isReference;
|
return isLValueReference() || isRValueReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLValueReference() {
|
||||||
|
return isLValueReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRValueReference() {
|
||||||
|
return isRValueReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSigned() {
|
public boolean isSigned() {
|
||||||
|
@ -697,11 +724,11 @@ public class DemangledDataType extends DemangledType {
|
||||||
buffer.append(SPACE + PTR_NOTATION);
|
buffer.append(SPACE + PTR_NOTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReference) {
|
if (isLValueReference) {
|
||||||
buffer.append(SPACE + REF_NOTATION);
|
buffer.append(SPACE + REF_NOTATION);
|
||||||
if (isRValueReference) {
|
}
|
||||||
buffer.append(REF_NOTATION); // &&
|
else if (isRValueReference) {
|
||||||
}
|
buffer.append(SPACE + RIGHT_REF_NOTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the order of __ptr64 and __restrict can vary--with fuzzing...
|
// the order of __ptr64 and __restrict can vary--with fuzzing...
|
||||||
|
|
|
@ -870,7 +870,7 @@ public class GnuDemanglerParser {
|
||||||
}
|
}
|
||||||
else if (ch == '&') {
|
else if (ch == '&') {
|
||||||
if (!dt.isReference()) {
|
if (!dt.isReference()) {
|
||||||
dt.setReference();
|
dt.setLValueReference();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dt.setRValueReference();
|
dt.setRValueReference();
|
||||||
|
@ -1286,7 +1286,7 @@ public class GnuDemanglerParser {
|
||||||
dt.incrementPointerLevels();
|
dt.incrementPointerLevels();
|
||||||
}
|
}
|
||||||
else if (type.equals("&")) {
|
else if (type.equals("&")) {
|
||||||
dt.setReference();
|
dt.setLValueReference();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new DemanglerParseException("Unexpected charater inside of parens: " + type);
|
throw new DemanglerParseException("Unexpected charater inside of parens: " + type);
|
||||||
|
|
|
@ -1927,8 +1927,18 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertName(object, name, "WebCore", "TextCodecICU");
|
assertName(object, name, "WebCore", "TextCodecICU");
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
|
|
||||||
|
// 20230719: Note that argument in the following function is not correctly parsed.
|
||||||
|
// The argument is a non-pointer/ref reference to a function that returns void and
|
||||||
|
// which takes the argument list shown. Parser looks for double closing parenthesis,
|
||||||
|
// but that is found on the last argument of the template parameter. It actually needed
|
||||||
|
// to find the last closing parethesis and know that there could be nested pairs.
|
||||||
|
// Modification on 20230719 has "(* &&)" emitted in place of "(*)" because of lref/rref
|
||||||
|
// work in GP-3649, but the "&&" was found due to the closing parenthesis issue, which
|
||||||
|
// already existed.
|
||||||
|
// TODO: needs fixed
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"undefined WebCore::TextCodecICU::registerCodecs(void (*)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
"undefined WebCore::TextCodecICU::registerCodecs(void (* &&)(char const *,WTF::Function<std::__1::unique_ptr<WebCore::TextCodec,std::__1::default_delete<WebCore::TextCodec>> ()> &&))",
|
||||||
signature);
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.framework.options.Options;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.data.ParameterDefinition;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
|
@ -97,6 +98,29 @@ public class MicrosoftDemanglerAnalyzerTest extends AbstractGhidraHeadedIntegrat
|
||||||
assertEquals("undefined InvokeHelperV(void)", function.getSignature().toString());
|
assertEquals("undefined InvokeHelperV(void)", function.getSignature().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyComplicatedFunctionSignatureHavingReference() throws Exception {
|
||||||
|
|
||||||
|
String mangled = "?f2@@YAP6AP6AHH@ZP6ADD@Z@ZAAP6AP6AHH@Z0@Z@Z";
|
||||||
|
|
||||||
|
Address addr = addr("0x110");
|
||||||
|
createSymbol(addr, mangled);
|
||||||
|
|
||||||
|
analyze();
|
||||||
|
|
||||||
|
FunctionManager fm = program.getFunctionManager();
|
||||||
|
Function function = fm.getFunctionAt(addr);
|
||||||
|
assertNotNull(function);
|
||||||
|
ParameterDefinition[] params = function.getSignature().getArguments();
|
||||||
|
assertEquals(1, params.length);
|
||||||
|
ParameterDefinition param = params[0];
|
||||||
|
assertEquals("_func__func_int_int_ptr__func_char_char_ptr * * param_1",
|
||||||
|
param.toString());
|
||||||
|
assertEquals(
|
||||||
|
"_func__func_int_int_ptr__func_char_char_ptr * f2(_func__func_int_int_ptr__func_char_char_ptr * * param_1)",
|
||||||
|
function.getSignature().toString());
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -452,7 +452,8 @@ public class MDMangGhidra extends MDMang {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemangledFunctionReference processDemangledFunctionReference(MDModifierType refType) {
|
private DemangledFunctionReference processDemangledFunctionReference(MDModifierType refType) {
|
||||||
if (!((refType instanceof MDReferenceType) || (refType instanceof MDDataRightReferenceType))) {
|
if (!((refType instanceof MDReferenceType) ||
|
||||||
|
(refType instanceof MDDataRightReferenceType))) {
|
||||||
return null; // Not planning on anything else yet.
|
return null; // Not planning on anything else yet.
|
||||||
}
|
}
|
||||||
DemangledFunctionReference functionReference =
|
DemangledFunctionReference functionReference =
|
||||||
|
@ -610,18 +611,19 @@ public class MDMangGhidra extends MDMang {
|
||||||
// modifierType.getArrayString();
|
// modifierType.getArrayString();
|
||||||
// resultDataType.setArray();
|
// resultDataType.setArray();
|
||||||
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
||||||
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
DemangledDataType newResult =
|
||||||
resultDataType.incrementPointerLevels();
|
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
||||||
|
newResult.incrementPointerLevels();
|
||||||
if (modifierType.getCVMod().isConst()) {
|
if (modifierType.getCVMod().isConst()) {
|
||||||
resultDataType.setConst();
|
newResult.setConst();
|
||||||
}
|
}
|
||||||
if (modifierType.getCVMod().isVolatile()) {
|
if (modifierType.getCVMod().isVolatile()) {
|
||||||
resultDataType.setVolatile();
|
newResult.setVolatile();
|
||||||
}
|
}
|
||||||
if (modifierType.getCVMod().isPointer64()) {
|
if (modifierType.getCVMod().isPointer64()) {
|
||||||
resultDataType.setPointer64();
|
newResult.setPointer64();
|
||||||
}
|
}
|
||||||
return resultDataType;
|
return newResult;
|
||||||
}
|
}
|
||||||
// TODO: fix. Following is a kludge because DemangledObject has no
|
// TODO: fix. Following is a kludge because DemangledObject has no
|
||||||
// DemangledReference
|
// DemangledReference
|
||||||
|
@ -648,18 +650,19 @@ public class MDMangGhidra extends MDMang {
|
||||||
return fr;
|
return fr;
|
||||||
}
|
}
|
||||||
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
||||||
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
DemangledDataType newResult =
|
||||||
resultDataType.setReference(); // Not sure if we should do/use this.
|
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
||||||
|
newResult.setLValueReference();
|
||||||
if (modifierType.getCVMod().isConst()) {
|
if (modifierType.getCVMod().isConst()) {
|
||||||
resultDataType.setConst();
|
newResult.setConst();
|
||||||
}
|
}
|
||||||
if (modifierType.getCVMod().isVolatile()) {
|
if (modifierType.getCVMod().isVolatile()) {
|
||||||
resultDataType.setVolatile();
|
newResult.setVolatile();
|
||||||
}
|
}
|
||||||
if (modifierType.getCVMod().isPointer64()) {
|
if (modifierType.getCVMod().isPointer64()) {
|
||||||
resultDataType.setPointer64();
|
newResult.setPointer64();
|
||||||
}
|
}
|
||||||
return resultDataType;
|
return newResult;
|
||||||
}
|
}
|
||||||
// TODO: fix. Following is a kludge because DemangledObject has no DemangledReference
|
// TODO: fix. Following is a kludge because DemangledObject has no DemangledReference
|
||||||
// with corresponding referencedType.
|
// with corresponding referencedType.
|
||||||
|
@ -725,7 +728,7 @@ public class MDMangGhidra extends MDMang {
|
||||||
}
|
}
|
||||||
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
//Processing the referenced type (for Ghidra, and then setting attributes on it)
|
||||||
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
processDataType(resultDataType, (MDDataType) modifierType.getReferencedType());
|
||||||
resultDataType.setReference(); // Not sure if we should do/use this.
|
resultDataType.setRValueReference();
|
||||||
if (modifierType.getCVMod().isConst()) {
|
if (modifierType.getCVMod().isConst()) {
|
||||||
resultDataType.setConst();
|
resultDataType.setConst();
|
||||||
}
|
}
|
||||||
|
@ -808,7 +811,7 @@ public class MDMangGhidra extends MDMang {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (datatype instanceof MDReferenceType) {
|
else if (datatype instanceof MDReferenceType) {
|
||||||
resultDataType.setReference();
|
resultDataType.setLValueReference();
|
||||||
}
|
}
|
||||||
else if (datatype instanceof MDArrayBasicType) {
|
else if (datatype instanceof MDArrayBasicType) {
|
||||||
resultDataType.setArray(1);
|
resultDataType.setArray(1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue