Skip to content

[RISC-V] Unlinked obj file branches contain a fake infinite-loop destination. #104853

Open
@patrick-rivos

Description

@patrick-rivos

Using the same input assembly file from:

int x = 0;
int min(int y)
{
	while (x != 192) {
		x += 1;
	}
	return y;
}
int main() {
	min(1);
}

gnu-as assembled program looks normal:

map-binutils.o: file format elf64-littleriscv

Disassembly of section .text:

0000000000000000 <min>:
       0: 000005b7      lui     a1, 0x0
       4: 0005a683      lw      a3, 0x0(a1)
       8: 0c000613      li      a2, 0xc0
       c: 00c68463      beq     a3, a2, 0x14 <.LBB0_2>
      10: 00c5a023      sw      a2, 0x0(a1)

0000000000000014 <.LBB0_2>:
      14: 8082          ret

0000000000000016 <main>:
      16: 00000537      lui     a0, 0x0
      1a: 00052603      lw      a2, 0x0(a0)
      1e: 0c000593      li      a1, 0xc0
      22: 00b60463      beq     a2, a1, 0x2a <.LBB1_2>
      26: 00b52023      sw      a1, 0x0(a0)

000000000000002a <.LBB1_2>:
      2a: 4501          li      a0, 0x0
      2c: 8082          ret
      2e: 0000          unimp

But LLVM's obj file looks like: (each branch is an infinite loop)

map.o:  file format elf64-littleriscv

Disassembly of section .text:

0000000000000000 <min>:
       0: 000005b7      lui     a1, 0x0
       4: 0005a683      lw      a3, 0x0(a1)
       8: 0c000613      li      a2, 0xc0
       c: 00c68063      beq     a3, a2, 0xc <min+0xc>
      10: 00c5a023      sw      a2, 0x0(a1)
      14: 8082          ret

0000000000000016 <main>:
      16: 00000537      lui     a0, 0x0
      1a: 00052603      lw      a2, 0x0(a0)
      1e: 0c000593      li      a1, 0xc0
      22: 00b60063      beq     a2, a1, 0x22 <main+0xc>
      26: 00b52023      sw      a1, 0x0(a0)
      2a: 4501          li      a0, 0x0
      2c: 8082          ret

gnu-objdump and llvm-objdump agree on this output so it's probably not on the objdump side of things.

When actually linked the offsets are updated to the correct addresses (with both lld/ld):

000000000001129e <min>:
   1129e: 000155b7     	lui	a1, 0x15
   112a2: 2f05a683     	lw	a3, 0x2f0(a1)
   112a6: 0c000613     	li	a2, 0xc0
   112aa: 00c68463     	beq	a3, a2, 0x112b2 <min+0x14>
   112ae: 2ec5a823     	sw	a2, 0x2f0(a1)
   112b2: 8082         	ret

I think the actual dests in the LLVM obj file are encoded using R_RISCV_BRANCH.

This behavior makes inspecting unlinked object files unintuitive at first glance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions