binaryninja-api
binaryninja-api copied to clipboard
MIPS rebasing doesn't adjust $gp.
Version and Platform (required): 3.5
Bug Description: MIPS rebasing doesn't adjust $gp, references to $gp-sensitive stuff is lost on rebase, like the global offset table.
Steps To Reproduce: Open the attached binary: libhdk-mips-elf.zip
Navigate to the memcpy plt stub:
00018900 int32_t memcpy()
00018900 1080998f lw $t9, -0x7ff0($gp) {0x0} {_GLOBAL_OFFSET_TABLE_}
It correctly gets the pointer to the _GLOBAL_OFFSET_TABLE_ at 0x2c400 using $gp and we can check the math in the python console:
>>> hex(bv.global_pointer_value.value - 0x7ff0)
'0x2c400'
>>> hex(bv.symbols['_GLOBAL_OFFSET_TABLE_'][0].address)
'0x2c400'
Now rebase the program to any address, say 0x1000 and the reference to the GOT is lost:
00019900 int32_t memcpy()
00019900 1080998f lw $t9, -0x7ff0($gp) {data_2c400}
Expected Behavior:
The reference to _GLOBAL_OFFSET_TABLE_ is maintained after rebasing.
Current workaround for this is to open the binary with options rather than rebasing after open.
I tested and found that with my recent changes on the global pointer value update, the global pointer value is already correctly updated after the rebasing. However, the function is not re-analyzed so it still has the old analysis. If I manually update the analysis then it works. The next step is to understand why we missed an analysis update for it
We are missing the analysis update because once we decide a function uses the gp value and update its analysis accordingly, the function's argument list no longer contains the gp register, and it is no longer considered using the gp. In other words, our "function uses gp" detection is only one-shot, when the gp value changes, either because the entire analysis state change, or, in the future, when a gp value is specified by the user (#5648), these functions all would not be updated properly.