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

We’ve covered offsets with base previously. There is a variation of such offsets commonly used in position-independent code which can be handled easily with a little trick.

Let’s consider this ARM function from an ARM32 firmware:

ROM:00000058 ; int sub_58()
ROM:00000058 sub_58                                  ; CODE XREF: sub_10A4:loc_50↑j
ROM:00000058                                         ; DATA XREF: sub_8D40+20↓r ...
ROM:00000058                 ADR             R0, off_88 ; R0 = 0x88
ROM:0000005C                 LDM             R0, {R10,R11} ; R10 = 0x3ADC0, R11 = 0x3AE00
ROM:00000060                 ADD             R10, R10, R0 ; R10 = 0x3ADC0+0x88
ROM:00000064                 SUB             R7, R10, #1
ROM:00000068                 ADD             R11, R11, R0 ; R11 = 0x3AE00+0x88
ROM:0000006C loc_6C                                  ; DATA XREF: sub_58+20↓o
ROM:0000006C                 CMP             R10, R11
ROM:00000070                 BEQ             sub_D50
ROM:00000074                 LDM             R10!, {R0-R3}
ROM:00000078                 ADR             LR, loc_6C
ROM:0000007C                 TST             R3, #1
ROM:00000080                 SUBNE           PC, R7, R3
ROM:00000084                 BX              R3
ROM:00000084 ; End of function sub_58
ROM:00000084 ; ---------------------------------------------------------------------------
ROM:00000088 off_88          DCD dword_3ADC0         ; DATA XREF: sub_58↑o
ROM:00000088                                         ; sub_58+4↑o
ROM:0000008C                 DCD off_3AE00


IDA has converted the values at addresses 88 and 8C to offsets because they happen to be valid addresses, but if you look at what the code does (I’ve added comments describing what happens), we’ll see that both values are added to the address from which they’re loaded (0x88), i.e. they’re relative to their own position (or self-relative). 

To get the final value they refer to, we can use the action Edit > Operand type > Offset >Offset (user-defined) (shortcut CtrlR), and enter as the base either the address value (0x88), or, for the case of the value at 00000088, the IDC keyword here, which expands to the address under the cursor.

IDA calculates the final address and replaces the value with an expression which uses a special symbol ., which denotes the current address on ARM:

ROM:00000088 off_88          DCD off_3AE48 - .       ; DATA XREF: sub_58↑o

For the value at 0000008C, here will not work since it expands to 0x8c while the addend is 0x88. There are several options we can use:

  1. use the actual value 0x88 as the base
  2. use the expression here-4which resolves to 0x88.
  3. use here, but specify 4 in the Target delta field. 

IDA will use the delta as an additional adjustment for the expression:

ROM:0000008C                 DCD byte_3AE88+4 - .

Now we can see what addresses the function is actually using and analyze it further.

See also:

Igor’s tip of the week #105: Offsets with custom base

Igor’s tip of the week #21: Calculator and expression evaluation feature in IDA