[PATCH] D21215: [docs] Update AMDGPU relocation information

Tye, Tony via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 11 12:05:12 PDT 2016


Hi Rafeal,
Can you explain a bit more what you mean by "*assumes* the value is 32 bits and the linker errors if it is not”.  My understanding was that the relocation record explicitly “defines” what size of result it is producing and that is what the “Field” column specified.

But it sounds like you are describing that the linker performs the relocation expression at infinite precision (which effectively means 64 bit precision since that is the address size for the architecture) and then checks that the value will fit in the size of the destination defined by “Field”. If that is the case how does the linker handle whether the value is signed or unsigned? For example, the PC relative relocations can produce negative values, meaning that the top bits (namely the bits above the bits specified by Field) can either be all 1s or all 0s. Does the linker consider the value “in range” provided the top bits are either all 1s or all 0s, and out of range otherwise?

A similar question exists for the loader. Does the loader give an error if a relocation is out of range by the above definition? For example, if a location has a r_x86_32 relocation that the linker checked as being in range based on the preferred ELF load address, but due to not being able to be loaded at its preferred ELF load address the value becomes out of range, will the loader give an error?

So digging a bit deeper it seems the answer to that question is that the treatment of whether the value is considered signed or unsigned is defined by the relocation type. This is why X64 has R_X86_64_32 and R_X86_64_32S which only differ in whether the 32 bit value must either zero extend or sign extend to the required 64 bit value. Although not stated, it seems the PC relative relocations are treated as signed values.

If the answer to those questions is that the semantics of the relocation expression is to enforce range checking as described above, then I agree there should be separate relocation kinds for the HI/LO. Only the LO form would have the & 0xFFFFFFFF as the range checking rules should still apply to the HI form to ensure that the shifted bits have a value that fits in the 32 bit result (which it always will since the address size is 64 bits).

That would imply the relocations should be:

  =====================  =====  ==========  =============
  Relocation type        Value  Field       Calculation
  =====================  =====  ==========  =============
  ``R_AMDGPU_NONE``      0      ``none``    ``none``
  ``R_AMDGPU_ABS32_LO``  1      ``word32``  (S + A) & 0xFFFFFFFF
  ``R_AMDGPU_ABS32_HI``  2      ``word32``  (S + A) >> 32
  ``R_AMDGPU_ABS64``     3      ``word64``  S + A
  ``R_AMDGPU_REL32``     4      ``word32``  S + A - P
  ``R_AMDGPU_REL64``     5      ``word64``  S + A - P
  ``R_AMDGPU_ABS32``     6      ``word32``  S + A
  =====================  =====  ==========  =============

The R_AMDGPU_REL64 is required for the amd_kernel_code_t which contains a 64 bit displacement to the entry point of the code.

For DWARF, what relocations are used in relocatable object files (since they are eliminated in executable and shared library object files since they only reference symbols in non-allocated sections)? Are they only using R_AMDGPU_REL64 and/or R_AMDGPU_REL32?

R_AMDGPU_ABS32 is needed to support code objects generated for loading into 32 bit applications. These may require relocations of global variables initialized with the address of other global variables, and global addresses are 32 bits in 32 bit apps. It is effectively a range checked form of R_AMDGPU_ABS32_LO. It seems that unlike x64, which has both signed and unsigned forms R_X86_64_32 and R_X86_64_32S, only the unsigned form is needed. Such code objects would be executed in 32 bit mode so addresses are treated in the range 0..2^32-1, and so ELF addresses should also be required to be kept in that range.

Thanks,
-Tony

On Jun 11, 2016, at 8:57 AM, Rafael Espíndola <rafael.espindola at gmail.com<mailto:rafael.espindola at gmail.com>> wrote:


On Jun 11, 2016 1:42 AM, "Tye, Tony" <Tony.Tye at amd.com<mailto:Tony.Tye at amd.com>> wrote:
>
> The old R_AMDGPU_ABS32_LO and the new R_AMDGPU_ABS32 are in fact the same thing. The & 0xffffffff is implicitly done because the result of the R_AMDGPU_ABS32 is a word32 not a word64. So putting in the & 0xffffffff is redundant. The other ABI documents (such as for the x86) do not put in the & 0xffffffff so it seemed best to follow their conventions. R_AMDGPU_ABS32_HI and R_AMDGPU_ABS32 both return 32 bits as they are both defined as word32. They differ in that R_AMDGPU_ABS32_HI takes the address and shifts it right by 32 bits which effectively means that the top 32 bits of the 64 bit address are returned, not the bottom 32 bits.

It is not the same thing. For example r_x86_64_32 *assumes* the value is 32 bits and the linker errors if it is not.

The x86_64 abi has no need for a low or high relocation.

Since you need a high, it is extremely likely you need a low.

Cheers,
Rafael

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160611/72be4fcf/attachment.html>


More information about the llvm-commits mailing list