In assembly there is only one explicit reference to the target function, and that's where its address is moved to the variable at point 1 (you can see that the reference is marked 'o' (offset) and not 'p' ([procedure] call)). While IDA could in theory track stack var assignments and add xrefs also at the points the variable is used for an indirect call (2 and 3), this:
- would increase analysis time for negligible benefit (an experienced user can easily see that
var_4
is called twice)
- is prone to false positives (e.g. if there's a function call before initialization and use of the variable, you can't be sure that it's not overwritten by the side-effects of the function)
- is easily defeatable (e.g. do some simple math on the pointer and IDA will be fooled).
So it's better to add only explicit cross-references and let the human decide if extra ones need to be added manually.
That said, IDA does some limited amount of register tracking to handle the most common situations, e.g.:
mov esi, ds:__imp__sprintf
push edi
lea edx, [esp+0BCh+szOffset]
push offset Format ; "%08X"
push edx ; Dest
call esi ; __imp__sprintf
You can see that it added a comment at the call esi
instruction with the actual destination loaded earlier into esi
. (it also adds a call xref in such case).
the reference
? The application stores the address of the function in[ebp+var_4]
and then calls whatever is at[ebp+var_4]
2 times. In this case it's the function it moved there. The original code could have been something like that: pastebin.com/0S83zEhpsub_4011C0
function has only one reference. In reference I mean IDA only recognizes one call to the function which is fromDATA XREF: sub_4011D0+5o