Skip to content

riscv_dis_fix_addr

Tsukasa OI edited this page Jul 30, 2022 · 21 revisions

Disassembler: Fix address printer

Conflicts With

Issue Solved

This bug is caused by address computation of maybe_print_address on disassembling RV32 programs.

Let me show the pseudocode of maybe_print_address:

if (high part of the register [for address sequence] is set)
{
    pd->print_addr = (high part) + offset;        // (1)
    unset high part (as used);
}
else if (base register == `gp' && __global_pointer$ is available)
    pd->print_addr = __global_pointer$ + offset;  // (2)
else if (base register == `tp' || base register == `zero')
    pd->print_addr = offset;                      // (3)
// Sign-extend a 32-bit value to 64-bit
if (instruction is ADDIW or C.ADDIW)
    pd->print_addr = (bfd_vma)(int32_t)pd->print_addr;

In here, it implicitly sign-extends an int-typed variable offset to generate an address. (3) is the direct cause of PR29342 but other locations have similar issue.

On an example provided by Anvin, IOREG_FOO has an address value of 0xffffff00. However, due to incorrect sign-extension, the disassembler considers that the sw instruction operates on an incorrect address 0xffffffff_ffffff00 even on RV32. This affects symbol lookup. So, we have to mask (and zero-extend) the address on RV32 to get correct address 0xffffff00.

Also, the background provided by Anvin gives us a context: highest address space may be important for some systems/programs. So, not only fixing PR29342, I decided to make the address -1 (originally reserved as a non-printing address) printable by separating (a) the address to print and (b) whether the address should be printed. This isn't zero-overhead but close to.

This patchset:

  1. fits an address into a 32-bit value on RV32 (resolves PR29342)
  2. makes the highest address printable (0xffffffff (RV32) and 0xffffffff_ffffffff (RV64) can be printed as a real symbol)
  3. clarifies the meaning of the wide argument (is_addiw fits the context).

It also has new testcases and a testcase modification (it seems lla32.d is affected by this patchset but not harmful so that modifying the testcase lla32.d seemed better).

Clone this wiki locally