Skip to content

Commit

Permalink
ctypesparser: borland array type and function type
Browse files Browse the repository at this point in the history
xvenge00 committed Mar 19, 2019
1 parent b522c84 commit 9c8e9d6
Showing 5 changed files with 120 additions and 11 deletions.
4 changes: 4 additions & 0 deletions include/retdec/ctypesparser/borland_ast_ctypes_parser.h
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
#include "retdec/demangler/borland_ast/rreference_type.h"
#include "retdec/demangler/borland_ast/template_node.h"
#include "retdec/demangler/borland_ast/type_node.h"
#include "retdec/ctypes/array_type.h"
#include "retdec/ctypes/module.h"
#include "retdec/ctypes/context.h"
#include "retdec/ctypes/function.h"
@@ -61,6 +62,9 @@ class BorlandToCtypesParser: public CTypesParser
ctypes::Function::Parameters parseFuncParameters(std::shared_ptr<demangler::borland::NodeArray> paramsNode);
ctypes::CallConvention parseCallConvention(demangler::borland::CallConv callConv);
ctypes::FunctionType::VarArgness parseVarArgness(bool isVarArg);
std::shared_ptr<ctypes::FunctionType> parsefuncType(std::shared_ptr<demangler::borland::FunctionTypeNode> funcTypeNode);
ctypes::FunctionType::Parameters parseFuncTypeParameters(std::shared_ptr<demangler::borland::NodeArray> paramsNode);
std::shared_ptr<ctypes::ArrayType> parseArrayType(std::shared_ptr<demangler::borland::ArrayNode> ArrayTypeNode);
};

} // ctypesparser
1 change: 1 addition & 0 deletions include/retdec/demangler/demangler_base.h
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ class Demangler

virtual std::string demangleToString(const std::string &mangled) = 0;

// TODO move to provider, demanglers could return ASTs
virtual void demangleToModule(
const std::string &mangled,
std::unique_ptr<retdec::ctypes::Module> &module) {};
69 changes: 61 additions & 8 deletions src/ctypesparser/borland_ast_ctypes_parser.cpp
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ inline ctypes::IntegralType::Signess toSigness(bool isUnsigned)
return isUnsigned ? ctypes::IntegralType::Signess::Unsigned : ctypes::IntegralType::Signess::Signed;
}

ctypes::IntegralType::Signess toSigness(const std::string &typeName) // TODO config
ctypes::IntegralType::Signess toSigness(const std::string &typeName) // TODO config
{
if (typeName.substr(0, 9) == "unsigned ") {
return ctypes::IntegralType::Signess::Unsigned;
@@ -36,7 +36,7 @@ ctypes::IntegralType::Signess toSigness(const std::string &typeName) // TODO con
return ctypes::IntegralType::Signess::Signed;
}

} // anonymous namespace
} // anonymous namespace

BorlandToCtypesParser::BorlandToCtypesParser() : CTypesParser() {}

@@ -96,6 +96,7 @@ std::shared_ptr<retdec::ctypes::Function> BorlandToCtypesParser::parseFunction(s

std::shared_ptr<ctypes::Type> BorlandToCtypesParser::parseType(std::shared_ptr<retdec::demangler::borland::TypeNode> typeNode)
{
// TODO function type
if (typeNode) {
switch (typeNode->kind()) {
case Kind::KIntegralType: {
@@ -133,6 +134,14 @@ std::shared_ptr<ctypes::Type> BorlandToCtypesParser::parseType(std::shared_ptr<r
auto namedType = parseNamedType(std::static_pointer_cast<demangler::borland::NamedTypeNode>(typeNode));
return std::static_pointer_cast<ctypes::Type>(namedType);
}
case Kind::KFunctionType: {
auto funcType = parsefuncType(std::static_pointer_cast<demangler::borland::FunctionTypeNode>(typeNode));
return std::static_pointer_cast<ctypes::Type>(funcType);
}
case Kind::KArrayNode: {
auto arrayType = parseArrayType(std::static_pointer_cast<demangler::borland::ArrayNode>(typeNode));
return std::static_pointer_cast<ctypes::Type>(arrayType);
}
default:
break;
}
@@ -146,7 +155,7 @@ std::shared_ptr<ctypes::IntegralType> BorlandToCtypesParser::parseIntegralType(
{
assert(integralNode && "Node cannot be null");

std::string name = integralNode->typeName(); // no qualifiers
std::string name = integralNode->typeName(); // no qualifiers
unsigned bitWidth = typeWidths[integralNode->typeName()];
ctypes::IntegralType::Signess signess = toSigness(integralNode->isUnsigned());

@@ -158,7 +167,7 @@ std::shared_ptr<ctypes::FloatingPointType> BorlandToCtypesParser::parseFloatingP
{
assert(floatNode && "Node cannot be null");

std::string name = floatNode->typeName(); // no qualifiers
std::string name = floatNode->typeName(); // no qualifiers
unsigned bitWidth = typeWidths[floatNode->typeName()];

return ctypes::FloatingPointType::create(context, name, bitWidth);
@@ -169,7 +178,7 @@ std::shared_ptr<ctypes::IntegralType> BorlandToCtypesParser::parseCharType(
{
assert(charNode && "Node cannot be null");

std::string name = charNode->typeName(); // no qualifiers
std::string name = charNode->typeName(); // no qualifiers
unsigned bitWidth = typeWidths[name];
ctypes::IntegralType::Signess signess = toSigness(name);

@@ -181,7 +190,7 @@ std::shared_ptr<ctypes::Type> BorlandToCtypesParser::parseBuiltInType(
{
assert(typeNode && "Node cannot be null");

std::string typeName = typeNode->typeName(); // no qualifiers
std::string typeName = typeNode->typeName(); // no qualifiers

if (typeName == "void") {
return ctypes::VoidType::create();
@@ -234,7 +243,7 @@ std::shared_ptr<ctypes::NamedType> BorlandToCtypesParser::parseNamedType(
{
assert(namedTypeNode && "Node cannot be null");

std::string name = namedTypeNode->name()->str(); // no qualifiers
std::string name = namedTypeNode->name()->str(); // no qualifiers
return ctypes::NamedType::create(context, name);
}

@@ -252,7 +261,23 @@ ctypes::Function::Parameters BorlandToCtypesParser::parseFuncParameters(
auto param = ctypes::Parameter("", type);
parameters.emplace_back(param);
}
return {parameters};
return parameters;
}

ctypes::FunctionType::Parameters BorlandToCtypesParser::parseFuncTypeParameters(
std::shared_ptr<retdec::demangler::borland::NodeArray> paramsNode)
{
ctypes::FunctionType::Parameters parameters{};
if (paramsNode == nullptr) {
return parameters;
}

for (unsigned i = 0; i < paramsNode->size(); ++i) {
auto paramNode = std::static_pointer_cast<demangler::borland::TypeNode>(paramsNode->get(i));
auto type = parseType(paramNode);
parameters.emplace_back(type);
}
return parameters;
}

ctypes::CallConvention BorlandToCtypesParser::parseCallConvention(retdec::demangler::borland::CallConv callConv)
@@ -280,5 +305,33 @@ ctypes::FunctionType::VarArgness BorlandToCtypesParser::parseVarArgness(bool isV
}
}

std::shared_ptr<ctypes::FunctionType> BorlandToCtypesParser::parsefuncType(
std::shared_ptr<retdec::demangler::borland::FunctionTypeNode> funcTypeNode)
{
std::shared_ptr<ctypes::Type> returnType = parseType(funcTypeNode->retType());
ctypes::FunctionType::Parameters parameters = parseFuncTypeParameters(funcTypeNode->params());
ctypes::CallConvention callConvention = parseCallConvention(funcTypeNode->callConv());
ctypes::Function::VarArgness varArgness = parseVarArgness(funcTypeNode->isVarArg());

return ctypes::FunctionType::create(context, returnType, parameters, callConvention, varArgness);
}

std::shared_ptr<ctypes::ArrayType> BorlandToCtypesParser::parseArrayType(
std::shared_ptr<retdec::demangler::borland::ArrayNode> arrayTypeNode)
{
ctypes::ArrayType::Dimensions dimensions;

auto pointee = arrayTypeNode->pointee();
dimensions.emplace_back(arrayTypeNode->size());
while (pointee->kind() == Kind::KArrayNode) {
dimensions.emplace_back(std::static_pointer_cast<demangler::borland::ArrayNode>(pointee)->size());
pointee = std::static_pointer_cast<demangler::borland::ArrayNode>(pointee)->pointee();
}

auto type = parseType(std::static_pointer_cast<demangler::borland::TypeNode>(pointee));

return ctypes::ArrayType::create(context, type, dimensions);
}

} // ctypesparser
} // retdec
15 changes: 12 additions & 3 deletions src/demangler/borland_demangler.cpp
Original file line number Diff line number Diff line change
@@ -77,22 +77,31 @@ void BorlandDemangler::demangleToModule(
{"void", 0},
{"bool", 1},
{"char", 8},
{"signed char", 8},
{"unsigned char", 8},
{"wchar_t", 32},
{"short", 16},
{"unsigned short", 16},
{"int", 32},
{"unsigned int", 32},
{"long", 64},
{"unsigned long", 64},
{"long long", 64},
{"unsigned long long", 64},
{"int64_t", 64},
{"uint64_t", 64},
{"float", 32},
{"double", 64},
{"long double", 96},
{"pointer", 32}
};
}; // TODO getvalordefault

static const ctypesparser::CTypesParser::TypeSignedness typeSignedness = {
{"wchar_t", ctypes::IntegralType::Signess::Unsigned},
{"char16_t", ctypes::IntegralType::Signess::Unsigned},
{"char32_t", ctypes::IntegralType::Signess::Unsigned}
};
{"char32_t", ctypes::IntegralType::Signess::Unsigned},
{"char", ctypes::IntegralType::Signess::Unsigned},
}; // TODO threeval signedness parser char

ctypesparser::BorlandToCtypesParser ctypesParser{};
ctypesParser.parseInto(astParser.ast(), module, typeWidths, typeSignedness);
42 changes: 42 additions & 0 deletions tests/ctypesparser/borland_ast_to_ctypes_tests.cpp
Original file line number Diff line number Diff line change
@@ -204,6 +204,48 @@ TEST_F(BorlandCtypesTests, VarArgness)
EXPECT_TRUE(std::static_pointer_cast<ctypes::ReferenceType>(param)->getReferencedType()->isIntegral());
}

TEST_F(BorlandCtypesTests, ArrayTypeTests)
{
mangledToCtypes("@foo$qpa3$a6$i");
EXPECT_TRUE(module->hasFunctionWithName("foo"));
auto func = module->getFunctionWithName("foo");
auto param = func->getParameter(1).getType();
EXPECT_TRUE(param->isPointer());

auto pointee = std::static_pointer_cast<ctypes::PointerType>(param)->getPointedType();

EXPECT_TRUE(pointee->isArray());

auto elemType = std::static_pointer_cast<ctypes::ArrayType>(pointee)->getElementType();
EXPECT_TRUE(elemType->isIntegral());

EXPECT_EQ(std::static_pointer_cast<ctypes::ArrayType>(pointee)->getDimensionCount(), 2);

ctypes::ArrayType::Dimensions expectedDimensions{3,6};
EXPECT_EQ(std::static_pointer_cast<ctypes::ArrayType>(pointee)->getDimensions(), expectedDimensions);
}

TEST_F(BorlandCtypesTests, FunctionPointerTests)
{
mangledToCtypes("@foo$qpqv$i");
EXPECT_TRUE(module->hasFunctionWithName("foo"));
auto func = module->getFunctionWithName("foo");
auto param = func->getParameter(1).getType();
EXPECT_TRUE(param->isPointer());

auto pointee = std::static_pointer_cast<ctypes::PointerType>(param)->getPointedType();

EXPECT_TRUE(pointee->isFunction());

auto funcType = std::static_pointer_cast<ctypes::FunctionType>(pointee);

EXPECT_EQ(funcType->getParameterCount(), 1);
EXPECT_TRUE(funcType->getParameter(1)->isVoid());
EXPECT_EQ(funcType->getCallConvention(), ctypes::CallConvention());
EXPECT_TRUE(funcType->getReturnType()->isIntegral());
}


} // namespace tests
} // namespace ctypesparser
} // namespace retdec

0 comments on commit 9c8e9d6

Please sign in to comment.