3

IDA (the interactive disassembler by hex-rays.com) reports native C++ functions (Android NDK, arm) as __fastcall, for example:

// int __fastcall QVariant::toULongLong(_DWORD, _DWORD); weak

By the way, this function is declared in the docs as

qulonglong QVariant::toULongLong ( bool * ok = 0 ) const

When I define a native function with __attribute__((fastcall)), I get

warning: 'fastcall' attribute directive ignored [-Wattributes]

Question: I need to call a library function whose prototype I can (hopefully) guess. How do I declare functions so that they would be called with the right calling convention (namely, the __fastcall one reported by IDA)?

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • 1
    `fastcall` makes no sense for ARM, since the first couple of function arguments are passed in registers anyway. Do you have an actual problem using this library? Otherwise it might just be a case of issue with IDA and how it chooses to present information to the user. – Michael Apr 16 '14 at 09:14
  • The actual problem using the library is that I have to guess the prototypes (including the return values). – 18446744073709551615 Apr 16 '14 at 09:21
  • Hm. So a function reported my the disassembler is reported as `__fastcall` but documented without attributes? Did you try to declare it (and other functions disassebled as `__fastcall`) without attributes yourself? – Arne Mertz Apr 16 '14 at 10:03
  • @Michael You were right, it is an issue with IDA: all functions are reported as __fastcall. E.g. `int __fastcall t1(int a1, int a2, int a3);` for `void t1()`, with a wrong number of arguments! – 18446744073709551615 Apr 16 '14 at 11:04
  • In some sense **all** ARM functions are all `__fastcall`. You don't need this annotation in your 'C' however. The compiler does it by default. **IDA** will have issues determining if a function takes arguments. It would have to analyze all callers to see what is `mov r{0-3},rN` to know how many register are used, especially in **leaf** functions. – artless noise Apr 16 '14 at 15:13

1 Answers1

2

IDA just uses fastcall for any calling convention involving registers. In the case of ARM, fastcall basically means "default calling convention".

Adding #define __fastcall to the source should let you compile it. However, there is an additional issue for this function:

Note that QVariant::toULongLong() is a C++ method, so the first argument shown by the decompiler is actually the hidden this pointer which is passed to all non-static methods of C++ classes. Since the decompiler does not support C++ it converts it to an explicit argument. You may need to undo this operation to make it valid C++ code.

Or you could just use the actual source code.

Igor Skochinsky
  • 24,629
  • 2
  • 72
  • 109