Search code examples
functionllvmstatic-analysis

Address of getCalledValue vs getCalledFunction LLVM


I'm trying to get the address of the called operand in a direct function call. I found two plausible ways of doing so, but to my surprise, they're not equivalent.

if (const auto call = dyn_cast<CallInst>(&inst)) {
    Addr calledAddr;
   
    const auto called = call->getCalledValue();
  
    // Get address of called value
    ss << called;
    ss >> std::hex >> calledAddr;
  
    // If it's a direct call
    if (const auto f = call->getCalledFunction()) {
        Addr funAddr;
 
        ss << cast<llvm::Value>(f);
        ss >> std::hex >> funAddr;
  
        // This assertion fails!
        assert (calledAddr == funAddr);
        ...

Why does the address of the called value differ from the address of the function cast to a value? I'm using llvm-10.0.0.


Solution

  • There seems to be a problem in the way you're recovering the address of your pointers (through what I assume is a std::stringstream).

    Consider these examples: https://godbolt.org/z/h5cbzco93 vs https://godbolt.org/z/rh18PjrsM .

    If you compare the addresses direclty your code should have worked:

    if (const CallInst* call = dyn_cast<CallInst>(&inst)) {
        const Value* called = call->getCalledValue();
      
        if (const Function* f = call->getCalledFunction()) {
            // compare direclty the address pointed by called and by f
            assert (called == f);
            ...
    

    Furthermore, if you check the implementation of CallBase::getCalledValue and CallBase::getCalledFunction you'll see that they fall-back to the same method call. The only difference is dyn_cast_or_null that will return null unless the called operand is a Function.

    Value *getCalledValue() const { return getCalledOperand(); }
    ...
    Function *getCalledFunction() const {
      return dyn_cast_or_null<Function>(getCalledOperand());
    }