This is an archive of the discontinued LLVM Phabricator instance.

[RISCV][LLD] Support R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128
Needs ReviewPublic

Authored by kito-cheng on Jan 30 2023, 2:53 AM.

Details

Reviewers
asb
jrtc27
MaskRay
Summary

Support for the uleb128 related relocation[1].

R_RISCV_SET_ULEB128 should defer the relocation until
R_RISCV_SUB_ULEB128 appear since the symbol address of
R_RISCV_SET_ULEB128 might not fit the space of the current ULEB128
value, e.g. current ULEB128 value occupy 2 byte only, but the address of symbol
might not fit in 2 byte, it only fit for the address difference of
R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128.

R_RISCV_SUB_ULEB128 must come after R_RISCV_SET_ULEB128, and rely value
of previous R_RISCV_SET_ULEB128 relocation.

[1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/361

Diff Detail

Event Timeline

kito-cheng created this revision.Jan 30 2023, 2:53 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 30 2023, 2:53 AM
kito-cheng requested review of this revision.Jan 30 2023, 2:53 AM
kito-cheng edited the summary of this revision. (Show Details)May 24 2023, 10:03 AM
NOTE: psABI spec has merged and binutils support also merged into trunk.
kito-cheng planned changes to this revision.May 24 2023, 10:07 AM

Seem like I need to add at least one test case.

evandro removed a subscriber: evandro.May 24 2023, 1:48 PM

Changes:

  • add testcase.
asb added a comment.Jul 26 2023, 4:51 AM

Just cross-linking to https://github.com/llvm/llvm-project/issues/64102 - as we discussed at the last RISC-V LLVM sync-up we really would like to land this and get it into the LLVM 17 branch if possible, to avoid compatibility issues with the next binutils release.

Just cross-linking to https://github.com/llvm/llvm-project/issues/64102 - as we discussed at the last RISC-V LLVM sync-up we really would like to land this and get it into the LLVM 17 branch if possible, to avoid compatibility issues with the next binutils release.

I'll go on a trip and may be slow to respond. I'll do my best and I think there is still plenty of time.

Just cross-linking to https://github.com/llvm/llvm-project/issues/64102 - as we discussed at the last RISC-V LLVM sync-up we really would like to land this and get it into the LLVM 17 branch if possible, to avoid compatibility issues with the next binutils release.

For cross reference. this review https://reviews.llvm.org/D142879 also needs to land together with this.

Just cross-linking to https://github.com/llvm/llvm-project/issues/64102 - as we discussed at the last RISC-V LLVM sync-up we really would like to land this and get it into the LLVM 17 branch if possible, to avoid compatibility issues with the next binutils release.

For cross reference. this review https://reviews.llvm.org/D142879 also needs to land together with this.

I tried the existing patches as such on top 17.x branch and it crashes lld

| 0  libLLVM-17.so            0x00007f1bef819be4 llvm::sys::RunSignalHandlers() + 52
| 1  libLLVM-17.so            0x00007f1bef819d56
| 2  libc.so.6                0x00007f1bee65b6e0
| 3  riscv64-yoe-linux-ld.lld 0x00005595e8159d5e lld::elf::Symbol::getVA(long) const + 30
| 4  riscv64-yoe-linux-ld.lld 0x00005595e8214dd1
| 5  riscv64-yoe-linux-ld.lld 0x00005595e81081be void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true>>(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true>>) + 1886
| 6  riscv64-yoe-linux-ld.lld 0x00005595e813b5a3
| 7  libLLVM-17.so            0x00007f1bef785fd6
| 8  libLLVM-17.so            0x00007f1bef786b84
| 9  libstdc++.so.6           0x00007f1bee8df5e3
| 10 libc.so.6                0x00007f1bee6a5d63
| 11 libc.so.6                0x00007f1bee7247e0
| riscv64-yoe-linux-clang: error: unable to execute command: Segmentation fault (core dumped)
|

@raj.khem ooops, thanks for report that, I am happy to debug that, so...it would be appreciate if you can provide files by -Wl,--reproduce=xx.tar :)

Chagnes:

  • Rebase and update testcase

@raj.khem ooops, thanks for report that, I am happy to debug that, so...it would be appreciate if you can provide files by -Wl,--reproduce=xx.tar :)

@kito-cheng here is a reproducer from sed, the same crash is happening in lot of packages.

https://uclibc.org/~kraj/test.zip

There is a script called doit.sh inside the zip file which has the lld cmdline to reproduce the crash.

jrtc27 requested changes to this revision.Jul 31 2023, 12:02 PM
  • What about relocations in non-SHF_ALLOC sections? Surely that can happen for debug info?
  • Test has no coverage of errors
lld/ELF/Arch/RISCV.cpp
112–114

This doesn't make grammatical sense. Please rewrite this to be in the style of elf::reportRangeError; I'd like to see it print something like:

error: foo.o+0x1234: ULEB128 difference relocation pair overflow: 5 bytes needed but only 4 bytes allocated; references 'foo' - 'bar'
>>> 'foo' defined in foo.o
>>> 'bar' defined in bar.o
>>> referenced by bar.c:12
>>>               bar.o:(.baz+0x4)

and I guess also with the -fdebug-types-section message. reportRangeError does a lot of useful things, it would be a shame to deviate from that and lose the information.

333

config->wordsize * 8;

339

Why not just keep a pointer to the relocation around instead?

355

Why do you actually need to enforce this? So long as the SET/SUB pairs are adjacent it's fine

365

There are two cases this handles:

  1. a SUB with no preceding SET
  2. a SUB with a different preceding SET

This error isn't really correct. What you want to say is that you've found a SUB which is not, when looking at solely ULEB128 relocations, directly preceded by its corresponding SET.

371

What if this walks off the end of the buffer? It's an obscure edge case but could happen if you have a too-small buffer at the end of the file. Then we'll crash rather than catch the error early. Check getULEB128Size first.

This revision now requires changes to proceed.Jul 31 2023, 12:02 PM
kito-cheng planned changes to this revision.Aug 8 2023, 8:36 AM

I am cooking some better way to resolve this, relocateNonAlloc case is harder to handle than I think.

Some ideas I tried:

  • Introduce global variable to record prev relocation, binutils implementation this trick, but I know it's bad idea in lld, so I am not plan to going this way.
  • Did ULEB128 relocation at elf::riscvFinalizeRelax, which will cause performance issue, more memory usage...and also kind of layer violation, I have workable patch for this, but I don't think it's acceptable (I won't accept that if I am reviewer too...:P)
  • Pass pointer to Relocation rather than reference for TargetInfo::relocate(), so that I can get last relocation *in theory*, but I found it not work since relocateNoSym will pass local variable...
  • Introduce new API into TargetInfo: TargetInfo::relocatePair(), I am working on this approach now, just need few more time to cook to patch, I guess this should be better than above approach.

Changes:

  • Rewrite in different way - introduce R_RELOCATE_PAIR_FIRST and R_RELOCATE_PAIR_SECOND.
  • Add testcases to cover negative test and ULEB128 relocations in non-alloc section.
This comment was removed by aaronpuchert.