foss-for-synopsys-dwc-arc-processors/toolchain

Wrong sign extension for 32bit relocations

BrunoASMauricio opened this issue · 2 comments

The following minimal example showcases how the 32 bit relocation symbol R_ARC_32_ME is malfunctioning.

asm.S

.text
.global main
.align 4
main:

1001:
  st 1, [0xF0000008]
  j @1001b

tarc.ld

ENTRY(main)
SECTIONS
{
 . = 0x80000100;
 .text : { *(.text) }
}

Compiling it with:
arc64-elf-gcc asm.S -mcpu=hs6x --specs=nsim.specs -T tarc.ld -nostartfiles -nostdlib

Yields

/tmp/ccpBYbhK.o: in function `main':
(.text+0xc): relocation truncated to fit: R_ARC_32_ME against `no symbol'
collect2: error: ld returned 1 exit status

This happens because the 0x8000_0000 gets sign extended when it shouldn't. Replacing that value with 0x7000_0000 "fixes this".
It is expected for these values to be unsigned.

After cross-referencing the 32 bit relocations that are set as "signed" in include/elf/arc-reloc.def with the ABI, we can take two conclusions:

  1. ARC_32_ME_S is NOT IN THE ABI, nor does it seem to be used anywhere (created issue #565 for this)
  2. There are quite a few 32 bit relocations that the ABI does not specify are signed/unsigned but are set as signed. A table of the respective entries in the ABI follows:
Enum Hex ELF Reloc Type Description Details
18 0x12 R_ARC_SDA32 SDA relocation word32 = ME ((S+A)-SDA_BASE)
27 0x1b R_ARC_32_ME Runtime relocation word32 = ME (S + A)
30 0x1e R_ARC_SDA32_ME SDA relocation word32 = ME ((S+A)-SDA_BASE)
49 0x31 R_ARC_32_PCREL PC-relative (data) word32 = (S+A-PDATA)
50 0x32 R_ARC_PC32 PC-relative word32 = ME (S+A-P)
51 0x33 R_ARC_GOTPC32 PC-relative GOT reference word32 = ME (GOT + G + A - P)
52 0x34 R_ARC_PLT32 PC-relative (PLT) word32 = ME (L+A-P)
54 0x36 R_ARC_GLOB_DAT GOT relocation word32= S
55 0x37 R_ARC_JMP_SLOT Runtime relocation word32 = ME(S)
56 0x38 R_ARC_RELATIVE Runtime relocation word32 = ME(B+A)
57 0x39 R_ARC_GOTOFF GOT relocation word32 = ME(S+A-GOT)
58 0x3a R_ARC_GOTPC PC-relative (GOT) word32 = ME(GOT_BEGIN - P)
98 0x62 R_ARC_PCLO32_ME_2 PC-relative address word32 = ME ((S + A - P ) >> 2)
99 0x63 R_ARC_PLT34 PC-relative (PLT) word32 = ME ((L + A - P ) >> 2)

@claziss besides R_ARC_32_ME, which of these should be set to bitfield?

@BrunoASMauricio corrected relocs types:

Enum Hex ELF Reloc Type Type Details
18 0x12 R_ARC_SDA32 signed word32 = ((S+A)-SDA_BASE)
27 0x1b R_ARC_32_ME bitfiled word32 = ME (S + A)
30 0x1e R_ARC_SDA32_ME signed word32 = ME ((S+A)-SDA_BASE)
49 0x31 R_ARC_32_PCREL signed word32 = (S+A-PDATA)
50 0x32 R_ARC_PC32 signed word32 = ME (S+A-P)
51 0x33 R_ARC_GOTPC32 signed word32 = ME (GOT + G + A - P)
52 0x34 R_ARC_PLT32 signed word32 = ME (L+A-P)
54 0x36 R_ARC_GLOB_DAT bitfiled word32= S
55 0x37 R_ARC_JMP_SLOT bitfiled word32 = ME(S)
56 0x38 R_ARC_RELATIVE bitfiled word32 = ME(B+A)
57 0x39 R_ARC_GOTOFF signed word32 = ME(S+A-GOT)
58 0x3a R_ARC_GOTPC signed word32 = ME(GOT_BEGIN - P)
98 0x62 R_ARC_PCLO32_ME_2 signed word32 = ME ((S + A - P ) >> 2)
99 0x63 R_ARC_PLT34 signed word32 = ME ((L + A - P ) >> 2)