Igor’s tip of the week #16: Cross-references
A reference or direction in one place in a book or other source of information to information at another place in the same work
To help you during analysis, IDA keeps track of cross-references (or xrefs for short) between different parts of the program. You can inspect them, navigate them or even add your own to augment the analysis and help IDA or the decompiler.
Types of cross-references
There are two groups of cross-references:
- code cross-references indicate a relationship between two areas of code:
- jump cross-reference indicates conditional or unconditional transfer of execution to another location.
- call cross-reference indicates a function or procedure call with implied return to the address following the call instruction.
- flow cross-reference indicates normal execution flow from current instruction to the next. This xref type is rarely shown explicitly in IDA but is used extensively by the analysis engine and plugin/script writers need to be aware of it.
- data cross-references are used for references to data, either from code or from other data items:
- read cross-reference indicates that the data at the address is being read from.
- write cross-reference indicates that the data at the address is being written to.
- offset cross-reference indicates that the address the of the item is taken but not explicitly read or written.
- structure cross-references are added when a structure is used in the disassembly or embedded into another structure.
The cross-reference types may be denoted by single-letter codes which are described in IDA’s help topic “Cross reference attributes”.
Inspecting and navigating cross-references
In the graph view, code cross-references are shown as edges (arrows) between code blocks. You can navigate by following the arrows visually or double-clicking.
In text mode, cross-references to the current address are printed as comments at the end of the line. By default, maximum two references are printed; if there are more, ellipsis (…) is shown. You can increase the amount of printed cross-references in Options > General… Cross-references tab.
Only explicit references are shown in comments; flow cross-references are not displayed in text mode. However, the absence of a flow cross-reference (end of code execution flow) is shown by a dashed line; usually it’s seen after unconditional jumps or returns but can also appear after calls to non-returning functions.
To navigate to the source of the cross-reference, double-click or press Enter on the address in the comment.
X is probably the most common and useful shortcut: press it to see the list of cross-references to the identifier under cursor. Pick an item from the list to jump to it. The shortcut works not only for disassembly addresses but also for stack variables (in a function) as well as structure and enum members.
Ctrl–X works similarly but shows the list of cross-references to the current address, regardless of where the cursor is in the line. For example, it is useful when you need to check the list of callers of the current function while being positioned on its first instruction.
Ctrl–J, on the other hand, shows a list of cross-references from the current address. Having multiple cross-references from a single location to multiple others is a somewhat rare situation but one case where it’s useful is switches (table jumps): using this shortcut on the indirect jump instructions allows you to quickly see and jump to any of the switch cases.
If you forget the shortcuts or simply prefer using the mouse, you can find the corresponding menu items in the Jump menu (and sometimes in the context menu).