[all-commits] [llvm/llvm-project] 1df5ea: [RISCV] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_UL...

Fangrui Song via All-commits all-commits at lists.llvm.org
Thu Nov 9 09:27:48 PST 2023


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 1df5ea29b43690b6622db2cad7b745607ca4de6a
      https://github.com/llvm/llvm-project/commit/1df5ea29b43690b6622db2cad7b745607ca4de6a
  Author: Fangrui Song <i at maskray.me>
  Date:   2023-11-09 (Thu, 09 Nov 2023)

  Changed paths:
    M llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
    M llvm/include/llvm/MC/MCAsmBackend.h
    M llvm/include/llvm/MC/MCFixup.h
    M llvm/include/llvm/MC/MCFragment.h
    M llvm/lib/MC/MCAsmBackend.cpp
    M llvm/lib/MC/MCAssembler.cpp
    M llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
    M llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
    M llvm/test/MC/ELF/RISCV/gen-dwarf.s
    A llvm/test/MC/RISCV/leb128.s

  Log Message:
  -----------
  [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




More information about the All-commits mailing list