[RISCV] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 for .uleb128 directives
For a label difference like `.uleb128 A-B`, MC folds A-B even if A and B are separated by a RISC-V linker-relaxable instruction. This incorrect behavior is currently abused by DWARF v5 .debug_loclists/.debug_rnglists (DW_LLE_offset_pair/DW_RLE_offset_pair entry kinds) implemented in Clang/LLVM (see https://github.com/ClangBuiltLinux/linux/issues/1719 for an instance). https://github.com/riscv-non-isa/riscv-elf-psabi-doc/commit/96d6e190e9fc04a8517f9ff7fb9aed3e9876cbd6 defined R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128. This patch generates such a pair of relocations to represent A-B that should not be folded. GNU assembler computes the directive size by ignoring shrinkable section content, therefore after linking the value of A-B cannot use more bytes than the reserved number (`final size of uleb128 value at offset ... exceeds available space`). We make the same assumption. ``` w1: call foo w2: .space 120 w3: .uleb128 w2-w1 # 1 byte, 0x08 .uleb128 w3-w1 # 2 bytes, 0x80 0x01 ``` We do not conservatively reserve 10 bytes (maximum size of an uleb128 for uint64_t) as that would pessimize DWARF v5 DW_LLE_offset_pair/DW_RLE_offset_pair, nullifying the benefits of introducing R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations. The supported expressions are limited. For example, * non-subtraction `.uleb128 A` is not allowed * `.uleb128 A-B`: report an error unless A and B are both defined and in the same section The new cl::opt `-riscv-uleb128-reloc` can be used to suppress the relocations. Reviewed By: asb Differential Revision: https://reviews.llvm.org/D157657
parent
e17efa60
Please register or sign in to comment