Latest available version: IDA and decompilers v8.4.240320 see all releases
Hex-Rays logo State-of-the-art binary code analysis tools
email icon

Cross-references is one of the most useful features of IDA. For example, they allow you to see where a particular function is being called or referenced from, helping you to see how the function is used and understand its behavior better or discover potential bugs or vulnerabilities. For direct calls, IDA adds cross-references automatically, but in modern programs there are also many indirect calls which can’t always be resolved at disassembly time. In such cases, it is useful to have an option to set the target call address manually.

Indirect call types

Most instruction sets have some kind of an indirect call instruction. The most common one uses a processor register which holds the address of the function to be called:

x86/x64 and ARM can use almost any general-purpose register:

call edi (x86)
call rax (x64)
BLX R12 (ARM32)
BLX R3
BLR X8 (ARM64)

PowerPC is more limited and has to use dedicated ctr or lr registers:

mtlr r12
blrl

mr r12, r9
mtctr r9
bctrl

in MIPS, in theory any register can be used, but binaries conforming to the standard PIC ABI tend to use the register t9:

la      $t9, __cxa_finalize
lw      $a0, (_fdata - 0x111E0)($v0)  # void *
jalr    $t9 ; __cxa_finalize

In addition to simple register, some processors support more complex expressions. For example, on x86/x64 it is possible to use a register with offset, allowing to read a pointer value and jump to it in a single instruction:

call    dword ptr [eax+0Ch] (x86)
call    qword ptr [rax+98h] (x64)

Setting callee address

In some simple situations (e.g. the register is initialized shortly before the call), IDA is able to resolve it automatically and adds a comment with the target address, like in the MIPS example above, or this one:

In more complicated situations, especially involving multiple memory dereferences or runtime calculations, it is possible to specify the target address manually.  For this, use the standard plugin command available in Edit > Plugins > Change the callee address. The default shortcut is AltF11.

The plugin will ask you to enter the target address (you can also use a function name):

The call instruction will gain a comment with the target address, as well as a cross-reference:

Currently the plugin is implemented for x86/x64, ARM and MIPS. If you need to set or access this information programmatically, you can check how it works by consulting the source code in the SDK, under plugins/callee.