Wrong sign extension for 32bit relocations
BrunoASMauricio opened this issue · 2 comments
BrunoASMauricio commented
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.
BrunoASMauricio commented
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:
ARC_32_ME_S
is NOT IN THE ABI, nor does it seem to be used anywhere (created issue #565 for this)- 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?
claziss commented
@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) |