如何从Clang中获取函数指针的参数?

时间:2021-04-06 17:21:12

I am trying to analyse C source code with function calls within them. I am able to analyse normal function calls to get their arguments without problem using the source code below where ce is a CallExpr object:

我正在尝试分析C源代码中包含函数调用。我能够分析正常的函数调用来获得他们的参数,而不用使用下面的源代码,ce是一个CallExpr对象:

1.  if(ce != NULL) {            
2.      QualType q = ce->getType();
3.      const Type *t = q.getTypePtrOrNull();
4.
5.      if (t != NULL) {
6.          llvm::errs() << "TYPE: " << t->isFunctionPointerType() << " " << q.getAsString() << " " << t->isPointerType() << "\n";
7.      } else {
8.          llvm::errs() << "FUNCTION CE HAS NO TYPE?\n";
9.      }
10.
11.
12.     const Decl* D = ce ->getCalleeDecl();
13.     while(D->getPreviousDecl() != NULL) 
14.         D = D->getPreviousDecl();
15.         
16.     llvm::errs() << "Kind:  " << D->getDeclKindName() << "\n";
17.     
18.     FunctionDecl* fd = (FunctionDecl*) llvm::dyn_cast<FunctionDecl>(D);
19.     for(int x = 0; x< fd ->getNumParams(); x++) {
20.         if(fd ->getParamDecl(x)->getType()->isAnyPointerType()) {
21.             // Do Stuff Here
22.         } 
23.     }
24. }

The problem with the above source code comes on line 18, when I try to typecast the Decl from the CallExpr to a FunctionDecl, this results in fd becoming NULL if the CallExpr is from a function pointer call.

上面的源代码的问题出现在第18行,当我试图将Decl从CallExpr类型转换为FunctionDecl时,如果CallExpr来自函数指针调用,这将导致fd变为NULL。

I tried to debug by trying to print the kind on line 16. For function pointers, it specifies the Decl on 12 is a VarDecl, not a FunctionDecl like normal function calls.

我试图通过在第16行中打印这种类型来调试。对于函数指针,它指定12上的Decl是VarDecl,而不是像普通函数调用那样的FunctionDecl。

I also tried using the isFunctionPointerType(), but this is returning false.

我还尝试了使用isFunctionPointerType(),但是返回的是false。

Here is a piece of source code that results in a segfault:

下面是导致segfault的一段源代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    void* (*mp)(size_t size);
    void *mpp;

    mp = &malloc;
    mpp = mp(30);

    free(mpp);
    return (0);
}

Is there a way using clang to detect whether a CallExpr is a function pointer call? and if so, how to get a list of the arguments?

是否有一种方法可以使用clang来检测CallExpr是否为函数指针调用?如果是,如何得到参数列表?

I am using clang 3.1

我用的是clang 3.1

Thanks

谢谢

2 个解决方案

#1


0  

Use getDirectCallee() function (I am not sure if it is available in clang 3.1 or not) FunctionDecl *func = ce->getDirectCallee();

使用getDirectCallee()函数(我不确定clang 3.1是否可用)FunctionDecl *func = ce->getDirectCallee();

if (func != NULL){
    for(int i = 0; i < func->getNumParams(); i++){
        if(func->getParamDecl(i)->getType()->isFunctionPointerType()){
            // Do stuff here
        }
    }
}

#2


0  

You should get function prototype from pointer declaration, after that you will be able to get information about return type and parameters types:

您应该从指针声明中获得函数原型,然后您将能够获得关于返回类型和参数类型的信息:

clang::CallExpr* expr;
...
auto decl = expr->getCalleeDecl();
if (decl != nullptr) {
    if (decl->getKind() == clang::Decl::Var) {
        clang::VarDecl *varDecl = clang::dyn_cast<clang::VarDecl>(decl);
        if(varDecl->getType()->isFunctionPointerType() == true) {
            const clang::PointerType *pt = varDecl->getType()->getAs<clang::PointerType>();
            const clang::FunctionProtoType *ft = pt->getPointeeType()->getAs<clang::FunctionProtoType>();
            if (ft != nullptr) {
                std::string retTypeName = ft->getReturnType().getAsString();
                ...
                auto paramsCount = funcType->getNumParams();
                for (size_t i = 0; i < paramsCount; ++i) {
                    clang::QualType paramType = funcType->getParamType(i);
                    std::string paramTypeName = paramType.getAsString();
                    ...
                }
            }
        }
    }
}

#1


0  

Use getDirectCallee() function (I am not sure if it is available in clang 3.1 or not) FunctionDecl *func = ce->getDirectCallee();

使用getDirectCallee()函数(我不确定clang 3.1是否可用)FunctionDecl *func = ce->getDirectCallee();

if (func != NULL){
    for(int i = 0; i < func->getNumParams(); i++){
        if(func->getParamDecl(i)->getType()->isFunctionPointerType()){
            // Do stuff here
        }
    }
}

#2


0  

You should get function prototype from pointer declaration, after that you will be able to get information about return type and parameters types:

您应该从指针声明中获得函数原型,然后您将能够获得关于返回类型和参数类型的信息:

clang::CallExpr* expr;
...
auto decl = expr->getCalleeDecl();
if (decl != nullptr) {
    if (decl->getKind() == clang::Decl::Var) {
        clang::VarDecl *varDecl = clang::dyn_cast<clang::VarDecl>(decl);
        if(varDecl->getType()->isFunctionPointerType() == true) {
            const clang::PointerType *pt = varDecl->getType()->getAs<clang::PointerType>();
            const clang::FunctionProtoType *ft = pt->getPointeeType()->getAs<clang::FunctionProtoType>();
            if (ft != nullptr) {
                std::string retTypeName = ft->getReturnType().getAsString();
                ...
                auto paramsCount = funcType->getNumParams();
                for (size_t i = 0; i < paramsCount; ++i) {
                    clang::QualType paramType = funcType->getParamType(i);
                    std::string paramTypeName = paramType.getAsString();
                    ...
                }
            }
        }
    }
}