<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/63390>63390</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
T bit on R_ARM relocations with odd addend is handled incorrectly
</td>
</tr>
<tr>
<th>Labels</th>
<td>
lld:ELF
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
john-brawn-arm
</td>
</tr>
</table>
<pre>
Many R_ARM relocations are defined in https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst as performing the operation `(S + A) | T` where
- S is the address of the symbol.
- A is the addend for the relocation.
- T is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 otherwise.
With the value of symbols having some special rules:
- If the symbol addresses an Arm instruction, its value is the address of the instruction (in a relocatable object, the offset of the instruction from the start of the section containing it).
- If the symbol addresses a Thumb instruction, its value is the address of the instruction with bit zero set (in a relocatable object, the section offset with bit zero set).
- For the purposes of relocation the value used shall be the address of the instruction (st_value & ~1).
This means that if we have a function whose first instruction is a thumb instruction at 0x1000, then if we have a relocation with addend 1 the final relocated value should be `(0x1000 + 1) | 1` i.e. 0x1001. However lld will currently calculate a value of 0x1002.
An example where this happens:
```
.text
.thumb_func
fn:
bx lr
.data
var1:
.word fn
var2:
.word fn+1
```
build with
```
llvm-mc -filetype=obj -triple=armv7a tmp.s -o tmp.o
ld.lld tmp.o -o a.out
llvm-objdump --syms --reloc --full-contents a.out
```
llvm-objdump output has
```
SYMBOL TABLE:
000200d4 l F .text 00000000 fn
Contents of section .data:
300d6 d5000200 d6000200 ........
```
fn starts at address 0x200d4, var1 has value 0x200d5 (correct) and var2 has value 0x200d6 (incorrect, should be 0x200d5).
Looking at lld it's not obvious to me how this should be fixed. It looks like this is happening because the way things are defined in the abi is "remove bit 0 at start, add the addend, then add bit 0 back in at the end" whereas what lld is doing is "take the symbol value as-is and add the addend". It looks like ARM::relocate is too late to do anything, as that's passed the S+A value from TargetInfo::relocateAlloc which got it from InputSectionBase::getRelocTargetVA which got it from Symbol::getVA.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVktv4zgS_jX0pSBBohI_Dj7I6TY2QLILxN5e7CmgxJLFhCIFkrLjOcxvH5CUH-l4pmeEwKHEen6sr4rMWrFTiEtyvyL33yZscK02yzfdqqQy7KASZrpJpflx-czUEV5ey5dnMCh1zZzQygIzCBwboZCDUNA611tSlISuCV3vhGuHKq11R-i6fHlOrG7cgRkkdM0qkTBG6LqSuiJ03TGh_GeGsinoZZUa64BZ6NE02nRC7cC1CLpHE0IAMs0InW-A0BWUhC6AzB5gS6YZHFo0SLJvJCsT2ICwQZNxbtBa0E14tceu0jI9iZVXYqg4NNqE10vOZ9GtF81BRDuOmR260RxsoGUW3LFH2Gy3r-v__vsBmOJXHk9xoAUG23boKhDKOjPU3gkpViCcd5CBdi2ag7A4eo6__xOuDeb2TA7os4l2LbRs71GyukOwPdaCSTCDxHAuQRcSeGz-JBYFpek-hUIfQDg7-rkN4pU4EDoXCtgJMVZJBF29Ye28pXB2TWPR3dJtjO5iXI6Zs4TFuFtr5ZhQPjnhCF2kv87mBrL_MJ2Dx7kSDn5Do8HH_esETwGPiX4x8Sn29Vhh_WB67YPWzVW1XR3xYJGDbZmUUOHfOAXrXqMioVP4Pb84jb_bVljokCkPAXO-jg_oiweBQTOoMf1WW4RGeBZe2xceXPczuMAcZB95lmUjFOqz2au8AigjyfIQfiOUr9QognzM2rZ6kNxnHIkezQe25ye2557tIsU0Os9T-Jc-4B4NSMnhIKSEejAGlZNHqJmsB8mcj-fMnaBHP-FTKsAP1vUSYyMB5wFrWd-julDJBxX_4nmmDj_cee3xefVYxi-NulCw-gBprv1Bypljcb1nJr-IpgdtODTqvEdv7NFVfjOiahABA9fe3JZy3yVdDUkjJPp-RYpvunqDxBnRS__GTLefMXBdn1pIdFjoUZmnHuDwxW-xVA_uyq6u3vjQ9ZAk9thZSJJwuJAkzSBl4umMytlrtVvRnazowfWD8431puzm_8-r_zzBtlw9fT_jk2UZzTJ-BxL8s47nA5CNzxnVh1MwvpGO9I0Hcoa6yDI-BX4fbQKfjot0fG5G1ajYy6ynxomv2UcIynPEn3SYFbEU4869p2-tjQk9ZREmhz_2L4LT2IzOog9XdBlN_Uz7J63ffQdlLpDDN9KZBaUd6Gov9GDBaegQWn2IFX-x2IgP5Ck8OpBav1uQ4n1kxZkY3nKFNRts7FAHdvQSavflphD6VyW8KqHUYKf3GJpk5kMLmPl8GOdX4_jcVfznKFyx-t3bYy7IBSEaGcssHNpTnha4DpMj-HPsHa9HRgSV2cT3NcW_uKU_p12-PPvKKMpTvwqjRGsIncVp4BqYOobcQx6xywawe2Z9K_f2N4SuytF7GH7bcI14VI3-bL6UnjmHVtQt7LTzl4Mg_6j6wW1iwa6Yxai1Q_fiFaO1H-UNxU1I_Cz-o0wnfFnwRbFgE1zm0_ksn8_zKZ20Sz6bYTYtZtM6Y3OsF9M7Wi-qnBUUMa8onYglzWiRTfNFfk_pHU1ni3ld0AJzhkW-oA25y7BjQqae0Kk2u4mwdsDltCgW2USyCqUNd1BKpeSkKL8_rQml_kpqlqEJVMPOkrtMCuvsxYoTTuJyG0pBqxvX0zBlNOenSRMKVXEZanCkjTxOBiOXf3F19f7Gf0lvdBz165CCJXQdsvgjAAD__1CkqNg">