[PATCH] D33280: [LLD][ELF] Support R_ARM_SBREL32 Relocation

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed May 17 10:33:31 PDT 2017


The TL;DR answer is that only RW symbols are used in the ABI defined
RWPI variant of the procedure calling standard [*].

In theory the R_ARM_SBREL32 relocation can use RO symbols as the
official ABI definition of B is loose.
"B(S) is the addressing origin of the output segment defining the
symbol S. The origin is not required to be the base address of the
segment. This value must always be word-aligned."

In the way  R_ARM_SBREL32 is used as part of -frwpi it only uses RW
symbols (RWPI = Read Write Position Independent). There is another
option -fropi (ROPI Read Only Position Independent) that addresses
read only data via an offset from the PC, this requires the code and
read-only data to be in the same PT_LOAD segment. This is covered a
bit more in the original RFC
http://lists.llvm.org/pipermail/llvm-dev/2015-December/093022.html

There are a couple of ways I've seen multiple bases be supported,
either for RO or RW. Both require additional compiler support and
involve either reserving another base register for RO or have the
first data member of RW contain an indirection table to another base.
These were both custom toolchain options and not part of the ABI.

[*] The ARM procedure call standard only defines RWPI
6.3 Read-Write Position Independence (RWPI)
Code compiled or assembled for execution environments that require
read-write position independence (for example, the single
address-space DLL-like model) use a static base to address writable
data. Core register r9 is renamed as SB and used to hold the static
base address: consequently this register may not be used for holding
other values at any time
[Although not mandated by this standard, compilers usually formulate
the address of a static datum by loading the offset of the datum from
SB, and adding SB to it. Usually, the offset is a 32-bit value loaded
PC-relative from a literal pool. Usually, the literal value is subject
to R_ARM_SBREL32-type relocation at static link time. The offset of a
datum from SB is clearly a
property of the layout of an executable, which is fixed at static link
time. It does not depend on where the data is loaded, which is
captured by the value of SB at run time. ]



On 17 May 2017 at 18:05, Rafael Avila de Espindola
<rafael.espindola at gmail.com> wrote:
> Peter Smith via Phabricator <reviews at reviews.llvm.org> writes:
>
>> peter.smith created this revision.
>> Herald added subscribers: javed.absar, emaste, rengolin, aemerson.
>>
>> This change adds support for the R_ARM_SBREL32 relocation. The relocation is a base relative relocation that is produced by clang/llvm when -frwpi is used. The use case for the -frwpi option is position independent data for embedded systems that do not have a GOT. With -frwpi all read-write data is accessed via an offset from a base register (usually r9), where r9 is set at run time to where the RW data has been loaded. The base of the RW data is known as the static base.
>>
>> Resolving the relocation is simple it is (S + A) - B where B is the static base. Choosing the location of and obtaining the value of the static base is more complicated. For lld I have chosen to use the base of the program segment containing the RW to be the static base. This supports the most common use case where there is a single PT_LOAD segment for the data.
>
> If the assembly has
>
>       .long   ro_symbol(sbrel)
>       .long   rw_symbol(sbrel)
>
> How does the program know at runtime to use a different base for each?
> Or it is just not valid to use sbrel with ro symbols?
>
> Cheers,
> Rafael


More information about the llvm-commits mailing list