diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -43,6 +43,8 @@ const uint8_t *loc) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; + void relocatePair(uint8_t *loc, const Relocation &relA, uint64_t valA, + const Relocation &relB, uint64_t valB) const override; bool relaxOnce(int pass) const override; }; @@ -101,6 +103,16 @@ (extractBits(imm, 4, 0) << 7); } +static void reportULEB128LengthExtend(uint8_t *loc, const RelType type, + Symbol &setSymbol, Symbol &subSymbol, + unsigned oldLength, unsigned newLength) { + ErrorPlace errPlace = getErrorPlace(loc); + error(errPlace.loc + "ULEB128 difference relocation pair overflow: " + + Twine(newLength) + " bytes needed but only " + Twine(oldLength) + + " bytes allocated; references '" + toString(setSymbol) + "' - '" + + toString(subSymbol) + "'"); +} + RISCV::RISCV() { copyRel = R_RISCV_COPY; pltRel = R_RISCV_JUMP_SLOT; @@ -277,6 +289,10 @@ case R_RISCV_SUB32: case R_RISCV_SUB64: return R_RISCV_ADD; + case R_RISCV_SET_ULEB128: + return R_RELOCATE_PAIR_FIRST; + case R_RISCV_SUB_ULEB128: + return R_RELOCATE_PAIR_SECOND; case R_RISCV_JAL: case R_RISCV_BRANCH: case R_RISCV_PCREL_HI20: @@ -313,6 +329,18 @@ } } +void RISCV::relocatePair(uint8_t *loc, const Relocation &relA, uint64_t valA, + const Relocation &relB, uint64_t valB) const { + unsigned oldLength; + decodeULEB128(loc, &oldLength); + uint64_t newVal = valA - valB; + unsigned newLength = getULEB128Size(newVal); + if (newLength <= oldLength) + encodeULEB128(newVal, loc, /*PadTo*/ oldLength); + else + reportULEB128LengthExtend(loc, relA.type, *relA.sym, *relB.sym, oldLength, + newLength); +} void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { const unsigned bits = config->wordsize * 8; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -635,6 +635,8 @@ case R_RELAX_TLS_LD_TO_LE_ABS: case R_RELAX_GOT_PC_NOPIC: case R_RISCV_ADD: + case R_RELOCATE_PAIR_FIRST: + case R_RELOCATE_PAIR_SECOND: return sym.getVA(a); case R_ADDEND: return a; @@ -861,7 +863,7 @@ break; } - for (const RelTy &rel : rels) { + for (auto [i, rel] : llvm::enumerate(rels)) { RelType type = rel.getType(config->isMips64EL); // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations @@ -940,6 +942,57 @@ continue; } + // Relocation pairs should appear together; we always handle them at the + // later one. + if (expr == R_RELOCATE_PAIR_FIRST || expr == R_RELOCATE_PAIR_SECOND) { + RelExpr expectedOther = expr == R_RELOCATE_PAIR_FIRST + ? R_RELOCATE_PAIR_SECOND + : R_RELOCATE_PAIR_FIRST; + bool foundPair = false; + const RelTy *otherRel = nullptr; + RelExpr otherExpr = R_NONE; + RelType otherType = R_NONE; + Symbol *otherSym = nullptr; + bool isSecondOne = false; + + auto getRelInfo = [&](size_t idx) { + otherRel = &rels[idx]; + otherType = otherRel->getType(config->isMips64EL); + otherSym = &getFile()->getRelocTargetSym(*otherRel); + otherExpr = target.getRelExpr(otherType, *otherSym, bufLoc); + }; + + // Try to look towards the front. + if (i + 1 < rels.size()) { + getRelInfo(i + 1); + if (expectedOther == otherExpr) + foundPair = true; + } + // Try to look towards the back. + if (!foundPair && i >= 1) { + getRelInfo(i - 1); + if (expectedOther == otherExpr) { + foundPair = true; + isSecondOne = true; + } + } + if (!foundPair) { + std::string msg = getLocation(offset) + + ": found orphan paired relocation " + toString(type) + + " against symbol '" + toString(sym) + "'"; + error(msg); + continue; + } + if (isSecondOne) + target.relocatePair( + bufLoc, Relocation{R_NONE, otherType, 0, 0, otherSym}, + SignExtend64(otherSym->getVA(addend)), + Relocation{R_NONE, type, 0, 0, + &getFile()->getRelocTargetSym(rel)}, + SignExtend64(sym.getVA(addend))); + continue; + } + std::string msg = getLocation(offset) + ": has non-ABS relocation " + toString(type) + " against symbol '" + toString(sym) + "'"; diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -57,6 +57,8 @@ R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, R_RELAX_TLS_LD_TO_LE_ABS, + R_RELOCATE_PAIR_FIRST, + R_RELOCATE_PAIR_SECOND, R_SIZE, R_TPREL, R_TPREL_NEG, diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -92,6 +92,9 @@ relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val); } virtual void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const; + void reportOrphanRelocationPair(uint8_t *loc, const Relocation &rel) const; + virtual void relocatePair(uint8_t *loc, const Relocation &relA, uint64_t valA, + const Relocation &relB, uint64_t valB) const; // Do a linker relaxation pass and return true if we changed something. virtual bool relaxOnce(int pass) const { return false; } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -159,17 +159,57 @@ uint64_t secAddr = sec.getOutputSection()->addr; if (auto *s = dyn_cast(&sec)) secAddr += s->outSecOff; - for (const Relocation &rel : sec.relocs()) { + for (auto [i, rel] : llvm::enumerate(sec.relocs())) { uint8_t *loc = buf + rel.offset; const uint64_t val = SignExtend64( sec.getRelocTargetVA(sec.file, rel.type, rel.addend, secAddr + rel.offset, *rel.sym, rel.expr), bits); - if (rel.expr != R_RELAX_HINT) + switch (rel.expr) { + case R_RELAX_HINT: + break; + case R_RELOCATE_PAIR_FIRST: { + if (i + 1 >= sec.relocs().size()) { + reportOrphanRelocationPair(loc, rel); + break; + } + + auto nextRel = sec.relocs()[i + 1]; + uint64_t nextVal = SignExtend64( + sec.getRelocTargetVA(sec.file, nextRel.type, nextRel.addend, + secAddr + nextRel.offset, *nextRel.sym, + nextRel.expr), + bits); + relocatePair(loc, rel, val, nextRel, nextVal); + } break; + case R_RELOCATE_PAIR_SECOND: + if (i < 1 || + (i > 1 && sec.relocs()[i - 1].expr != R_RELOCATE_PAIR_FIRST)) { + reportOrphanRelocationPair(loc, rel); + } + break; + default: relocate(loc, rel, val); + break; + } } } +void TargetInfo::reportOrphanRelocationPair(uint8_t *loc, + const Relocation &rel) const { + ErrorPlace errPlace = getErrorPlace(loc); + std::string msg = errPlace.loc + ": found orphan paired relocation " + + toString(rel.type) + " against symbol '" + + toString(*rel.sym) + "'"; + error(msg); +} + +void TargetInfo::relocatePair(uint8_t *loc, const Relocation &relA, + uint64_t valA, const Relocation &relB, + uint64_t valB) const { + llvm_unreachable("Target doesn't support relocatePair."); +} + uint64_t TargetInfo::getImageBase() const { // Use --image-base if set. Fall back to the target default if not. if (config->imageBase) diff --git a/lld/test/ELF/riscv-bad-uleb128-ext-len-noalloc.s b/lld/test/ELF/riscv-bad-uleb128-ext-len-noalloc.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-ext-len-noalloc.s @@ -0,0 +1,83 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: ULEB128 difference relocation pair overflow: 2 bytes needed but only 1 bytes allocated; references '.Lend_start' - '_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.debug_info + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .debug_info + Relocations: + - Symbol: .Lend_start + Type: R_RISCV_SET_ULEB128 + - Symbol: _start + Type: R_RISCV_SUB_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .debug_info + - Name: .rela.debug_info + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-bad-uleb128-ext-len.s b/lld/test/ELF/riscv-bad-uleb128-ext-len.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-ext-len.s @@ -0,0 +1,86 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: ULEB128 difference relocation pair overflow: 2 bytes needed but only 1 bytes allocated; references '.Lend_start' - '_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.data + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .data + Relocations: + - Symbol: .Lend_start + Type: R_RISCV_SET_ULEB128 + - Symbol: _start + Type: R_RISCV_SUB_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .data + - Name: .rela.data + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: '$d.1' + Section: .data + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-bad-uleb128-no-pair-1.s b/lld/test/ELF/riscv-bad-uleb128-no-pair-1.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-no-pair-1.s @@ -0,0 +1,84 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: found orphan paired relocation R_RISCV_SET_ULEB128 against symbol '.Lend_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.data + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .data + Relocations: + - Symbol: .Lend_start + Type: R_RISCV_SET_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .data + - Name: .rela.data + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: '$d.1' + Section: .data + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-bad-uleb128-no-pair-2.s b/lld/test/ELF/riscv-bad-uleb128-no-pair-2.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-no-pair-2.s @@ -0,0 +1,84 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: found orphan paired relocation R_RISCV_SUB_ULEB128 against symbol '_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.data + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .data + Relocations: + - Symbol: _start + Type: R_RISCV_SUB_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .data + - Name: .rela.data + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: '$d.1' + Section: .data + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-bad-uleb128-no-pair-3.s b/lld/test/ELF/riscv-bad-uleb128-no-pair-3.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-no-pair-3.s @@ -0,0 +1,81 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: found orphan paired relocation R_RISCV_SET_ULEB128 against symbol '.Lend_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.debug_info + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .debug_info + Relocations: + - Symbol: .Lend_start + Type: R_RISCV_SET_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .debug_info + - Name: .rela.debug_info + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-bad-uleb128-no-pair-4.s b/lld/test/ELF/riscv-bad-uleb128-no-pair-4.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-bad-uleb128-no-pair-4.s @@ -0,0 +1,81 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: yaml2obj a.yml -o a.o +# RUN: not ld.lld -T lds a.o -o 32c 2>&1 | FileCheck %s + +# CHECK: found orphan paired relocation R_RISCV_SUB_ULEB128 against symbol '_start' + +#--- a.yml + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x2 + Content: '01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010097000000E78000008280' + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '0000000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .text + Relocations: + - Offset: 0x1FE + Symbol: a + Type: R_RISCV_CALL_PLT + - Offset: 0x1FE + Type: R_RISCV_RELAX + - Name: .rela.debug_info + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x4 + Info: .debug_info + Relocations: + - Symbol: _start + Type: R_RISCV_SUB_ULEB128 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .debug_info + - Name: .rela.debug_info + - Name: .symtab +Symbols: + - Name: '$x.0' + Section: .text + - Name: a + Section: .text + Value: 0x206 + - Name: .Lend_start + Section: .text + Value: 0x206 + - Name: _start + Section: .text + Binding: STB_GLOBAL + Size: 0x206 +... + + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +} diff --git a/lld/test/ELF/riscv-relax-uleb128.s b/lld/test/ELF/riscv-relax-uleb128.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-relax-uleb128.s @@ -0,0 +1,77 @@ +# REQUIRES: riscv +## Relax R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +## RELAX +# RUN: llvm-mc -filetype=obj -triple=riscv32 -riscv-enable-uleb128 -mattr=+c,+relax a.s -o a.32c.o +# RUN: ld.lld -T lds a.32c.o -o 32c +# RUN: llvm-objdump -td -j .text -j .data -M no-aliases 32c | FileCheck %s --check-prefixes=RELAX,RELAX32 + +# RUN: llvm-mc -filetype=obj -triple=riscv64 -riscv-enable-uleb128 -mattr=+c,+relax a.s -o a.64c.o +# RUN: ld.lld -T lds a.64c.o -o 64c +# RUN: llvm-objdump -td -j .text -j .data -M no-aliases 64c | FileCheck %s --check-prefixes=RELAX,RELAX64 + +## --no-relax disables relaxation. +# RUN: ld.lld -T lds a.64c.o --no-relax -o 64c.norelax +# RUN: llvm-objdump -td -j .text -j .data -M no-aliases 64c.norelax | FileCheck %s --check-prefixes=NORELAX + +# RELAX32: 00010002 l .text 00000000 a +# RELAX32: 00010002 l .text 00000000 .Lend_start +# RELAX32: 00010000 g .text 00000002 _start + +# RELAX64: 0000000000010004 l .text 0000000000000000 a +# RELAX64: 0000000000010004 l .text 0000000000000000 .Lend_start +# RELAX64: 0000000000010000 g .text 0000000000000004 _start + +# RELAX-LABEL: <_start>: +# RELAX32-NEXT: 10000: 09 20 c.jal 0x10002 +# RELAX64-NEXT: 10000: ef 00 40 00 jal ra, 0x10004 +# RELAX-EMPTY: +# RELAX-NEXT: : +# RELAX32-NEXT: 10002: 82 80 c.jr ra +# RELAX64-NEXT: 10004: 82 80 c.jr ra +# RELAX-EMPTY: + +# RELAX-LABEL: <.data>: +# RELAX32: 20000: 82 80 +# RELAX32-NEXT: 20002: 80 80 +# RELAX32-NEXT: 20004: 00 +# RELAX64: 20000: 84 80 +# RELAX64-NEXT: 20002: 80 80 +# RELAX64-NEXT: 20004: 80 80 +# RELAX64-NEXT: 20006: 80 80 +# RELAX64-NEXT: 20008: 80 00 +# RELAX-EMPTY: + +# NORELAX-LABEL: <_start>: +# NORELAX: 10000: 97 00 00 00 auipc ra, 0 +# NORELAX-NEXT: e7 80 80 00 jalr ra, 8(ra) +# NORELAX-EMPTY: + +# NORELAX-LABEL: <.data>: +# NORELAX: 20000: 88 80 +# NORELAX-NEXT: 20002: 80 80 +# NORELAX-NEXT: 20004: 80 80 +# NORELAX-NEXT: 20006: 80 80 +# NORELAX-NEXT: 20008: 80 00 +# NORELAX-EMPTY: + + +#--- a.s +.global _start +_start: + call a # rv32c: c.jal; rv64c: jal +.Lend_start: +.size _start, . - _start + +a: + ret +.data +.uleb128 .Lend_start-_start + +#--- lds +SECTIONS { + .text 0x10000 : { *(.text) } + .data 0x20000 : { *(.data) } +}