Skip to content

Incorrect RISC-V relocation processing when multiple symbols have the same name #7809

@ArcaneNibble

Description

@ArcaneNibble

Version and Platform (required):

  • Binary Ninja Version: 5.2.8722 Personal (c75356aa)
  • OS: macOS
  • CPU Architecture: ARM64

Bug Description:
When disassembling a RISC-V relocatable (.o) file, references to data can end up pointing to the wrong location. Initial triage by bdash on Slack suggests that this may be due to multiple symbols with the same name.

Steps To Reproduce:

  1. Acquire a RISC-V binutils toolchain from somewhere.
  2. Run objdump -xdsS wch_nfca_pcd.o and observe the following disassembly, including a reference to gs_nfca_pcd_controller. This is within the nfca_pcd_lib_init function, which should be the first function in the file.
0000000c <.L4>:
   c:   4918                    lw      a4,16(a0)
   e:   00000797                auipc   a5,0x0
                        e: R_RISCV_PCREL_HI20   gs_nfca_pcd_controller
                        e: R_RISCV_RELAX        *ABS*
  12:   00078793                mv      a5,a5
                        12: R_RISCV_PCREL_LO12_I        .L0
                        12: R_RISCV_RELAX       *ABS*
  16:   414c                    lw      a1,4(a0)
  18:   cb98                    sw      a4,16(a5)
  1a:   4958                    lw      a4,20(a0)
  1c:   4510                    lw      a2,8(a0)
  1e:   4554                    lw      a3,12(a0)
  20:   00052803                lw      a6,0(a0)
  24:   cbd8                    sw      a4,20(a5)
  26:   4d18                    lw      a4,24(a0)
  28:   0107a023                sw      a6,0(a5) # e <.L4+0x2>
  2c:   c3cc                    sw      a1,4(a5)
  2e:   c790                    sw      a2,8(a5)
  30:   c7d4                    sw      a3,12(a5)
  32:   cf98                    sw      a4,24(a5)
  34:   4501                    li      a0,0
  36:   8082                    ret
  1. Run readelf -r wch_nfca_pcd.o and observe the following output. The R_RISCV_PCREL_LO12_I relocation points to symbol 0x3b (decimal 59), and readelf resolves the address to 0xe (where the R_RISCV_PCREL_HI20 relocation pointing to the actual target can be found).
0000000e  00000717 R_RISCV_PCREL_HI2 00000000   gs_nfca_pcd_controller + 0
0000000e  00000033 R_RISCV_RELAX                0
00000012  00003b18 R_RISCV_PCREL_LO1 0000000e   .L0  + 0
00000012  00000033 R_RISCV_RELAX                0
  1. Run readelf -s wch_nfca_pcd.o and observe the following output. Symbol 59 indeed contains the value 0xe. Note that symbol 58, with the same name, contains the value 0x0.
    58: 00000000     0 NOTYPE  LOCAL  DEFAULT    4 .L0
    59: 0000000e     0 NOTYPE  LOCAL  DEFAULT    4 .L0
    60: 00000038     0 NOTYPE  LOCAL  DEFAULT    4 .L2
    61: 0000000c     0 NOTYPE  LOCAL  DEFAULT    4 .L4
  1. Open the object file in Binary Ninja, switch to disassembly view, and observe the following output:
.L4:
0001000c  1849       lw      a4, 0x10(a0)
0001000e  97070000   auipc   a5, 0x0
00010012  93870775   addi    a5, a5, 0x750  {0x1075e}
00010016  4c41       lw      a1, 0x4(a0)
00010018  98cb       sw      a4, 0x10(a5)  {0x1076e}
0001001a  5849       lw      a4, 0x14(a0)
0001001c  1045       lw      a2, 0x8(a0)
0001001e  5445       lw      a3, 0xc(a0)
00010020  03280500   lw      a6, 0x0(a0)
00010024  d8cb       sw      a4, 0x14(a5)  {data_10772}
00010026  184d       lw      a4, 0x18(a0)
00010028  23a00701   sw      a6, 0x0(a5)  {0x1075e}
0001002c  ccc3       sw      a1, 0x4(a5)  {0x10762}
0001002e  90c7       sw      a2, 0x8(a5)  {0x10766}
00010030  d4c7       sw      a3, 0xc(a5)  {0x1076a}
00010032  98cf       sw      a4, 0x18(a5)  {data_10776}
00010034  0145       li      a0, 0x0
00010036  8280       ret
  1. Enter the following in the Binary Ninja Python console:
>>> bv.relocations_at(0x10012)
[<Relocation: ".L0 " @ 0x10000>]
  1. Scroll to the bottom of the disassembly view and observe that the correct address for the gs_nfca_pcd_controller symbol should be 0x10770:
.bss.gs_nfca_pcd_controller (NOBITS) section started  {0x10770-0x107a4}
00010770  gs_nfca_pcd_controller:
00010770  00 00                                            ..

00010772  int32_t data_10772 = 0x0
00010776  int32_t data_10776 = 0x0

0001077a                                00 00 00 00 00 00            ......
00010780  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00010790  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000107a0  00 00 00 00                                      ....
.bss.gs_nfca_pcd_controller (NOBITS) section ended  {0x10770-0x107a4}

Expected Behavior:
Binary Ninja has incorrectly resolved gs_nfca_pcd_controller to 0x1075e, which does not lie within any section. The reference to the object should be resolved correctly, just as binutils is able to.

Screenshots/Video Recording:
N/A

Binary:

wch_nfca_pcd.zip

Additional Information:
This binary contains currently-unsupported RISC-V bitmanip instructions as well as vendor-proprietary instructions that replace existing opcodes. As such, it will not fully disassemble (bitmanip instructions will be unknown, and the vendor instructions will incorrectly disassemble as double-precision floating-point load/stores). This does not affect relocation processing.

The R_RISCV_RELAX relocation causes [RISCV] Unknown relocation type 51 at XXXXX warnings in the logs. This can be ignored.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions