From 253125af0345649a7538864f7b55ec0c7139b242 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 26 Jun 2015 07:25:20 +0000 Subject: [PATCH] [Mips] Reject R_MIPS_CALL16 against local symbols llvm-svn: 240765 --- .../ELF/Mips/MipsRelocationPass.cpp | 47 +++++++++++----- lld/test/elf/Mips/validate-rel-03.test | 56 +++++++++++++++++++ 2 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 lld/test/elf/Mips/validate-rel-03.test diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index 13dceafd2dc9..fe762eaad153 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -547,15 +547,23 @@ static bool isBranchReloc(Reference::KindValue kind) { } static bool isGotReloc(Reference::KindValue kind) { - return kind == R_MIPS_GOT16 || kind == R_MIPS_GOT_HI16 || - kind == R_MIPS_GOT_LO16 || kind == R_MICROMIPS_GOT16 || - kind == R_MICROMIPS_GOT_HI16 || kind == R_MICROMIPS_GOT_LO16; + return kind == R_MIPS_GOT16 || kind == R_MICROMIPS_GOT16; +} + +static bool isAllGotReloc(Reference::KindValue kind) { + return isGotReloc(kind) || kind == R_MIPS_GOT_HI16 || + kind == R_MIPS_GOT_LO16 || kind == R_MICROMIPS_GOT_HI16 || + kind == R_MICROMIPS_GOT_LO16; } static bool isCallReloc(Reference::KindValue kind) { - return kind == R_MIPS_CALL16 || kind == R_MIPS_CALL_HI16 || - kind == R_MIPS_CALL_LO16 || kind == R_MICROMIPS_CALL16 || - kind == R_MICROMIPS_CALL_HI16 || kind == R_MICROMIPS_CALL_LO16; + return kind == R_MIPS_CALL16 || kind == R_MICROMIPS_CALL16; +} + +static bool isAllCallReloc(Reference::KindValue kind) { + return isCallReloc(kind) || kind == R_MIPS_CALL_HI16 || + kind == R_MIPS_CALL_LO16 || kind == R_MICROMIPS_CALL_HI16 || + kind == R_MICROMIPS_CALL_LO16; } static bool isGotDispReloc(Reference::KindValue kind) { @@ -610,8 +618,8 @@ void RelocationPass::handleReference(const MipsELFDefinedAtom &atom, handlePlain(atom, ref); else if (isBranchReloc(kind)) handleBranch(atom, ref); - else if (isGotReloc(kind) || isCallReloc(kind) || isGotDispReloc(kind) || - isGotPageReloc(kind) || kind == R_MIPS_EH) + else if (isAllGotReloc(kind) || isAllCallReloc(kind) || + isGotDispReloc(kind) || isGotPageReloc(kind) || kind == R_MIPS_EH) handleGOT(ref); else if (isTlsDtpReloc(kind)) ref.setAddend(ref.addend() - atom.file().getDTPOffset()); @@ -672,7 +680,8 @@ RelocationPass::collectReferenceInfo(const MipsELFDefinedAtom &atom, else _hasStaticRelocations.insert(ref.target()); - if (!isBranchReloc(refKind) && !isCallReloc(refKind) && refKind != R_MIPS_EH) + if (!isBranchReloc(refKind) && !isAllCallReloc(refKind) && + refKind != R_MIPS_EH) _requiresPtrEquality.insert(ref.target()); return std::error_code(); @@ -703,6 +712,15 @@ make_external_gprel32_reloc_error(const ELFLinkingContext &ctx, ref.target()->name() + " in file " + atom.file().path()); } +static std::error_code +make_local_call16_reloc_error(const ELFLinkingContext &ctx, + const DefinedAtom &atom, const Reference &ref) { + return make_dynamic_error_code("R_MIPS_CALL16 (11) relocation cannot be used " + "against local symbol " + + ref.target()->name() + " in file " + + atom.file().path()); +} + template std::error_code RelocationPass::validateRelocation(const DefinedAtom &atom, @@ -713,6 +731,9 @@ RelocationPass::validateRelocation(const DefinedAtom &atom, if (ref.kindValue() == R_MIPS_GPREL32 && !isLocal(ref.target())) return make_external_gprel32_reloc_error(this->_ctx, atom, ref); + if (isCallReloc(ref.kindValue()) && isLocal(ref.target())) + return make_local_call16_reloc_error(this->_ctx, atom, ref); + if (this->_ctx.getOutputELFType() != ET_DYN) return std::error_code(); @@ -765,7 +786,7 @@ static bool isMipsReadonly(const MipsELFDefinedAtom &atom) { template bool RelocationPass::mightBeDynamic(const MipsELFDefinedAtom &atom, Reference::KindValue refKind) const { - if (isGotReloc(refKind) || isCallReloc(refKind)) + if (isAllGotReloc(refKind) || isAllCallReloc(refKind)) return true; if (refKind != R_MIPS_32 && refKind != R_MIPS_64) @@ -902,10 +923,8 @@ template void RelocationPass::handleGOT(Reference &ref) { ref.setTarget(getGlobalGOTEntry(ref.target())); else if (isGotPageReloc(ref.kindValue())) ref.setTarget(getLocalGOTPageEntry(ref)); - else if (isLocal(ref.target()) && (ref.kindValue() == R_MIPS_GOT16 || - ref.kindValue() == R_MIPS_CALL16 || - ref.kindValue() == R_MICROMIPS_GOT16 || - ref.kindValue() == R_MICROMIPS_CALL16)) + else if (isLocal(ref.target()) && + (isCallReloc(ref.kindValue()) || isGotReloc(ref.kindValue()))) ref.setTarget(getLocalGOTPageEntry(ref)); else ref.setTarget(getLocalGOTEntry(ref)); diff --git a/lld/test/elf/Mips/validate-rel-03.test b/lld/test/elf/Mips/validate-rel-03.test new file mode 100644 index 000000000000..15aefa5114a8 --- /dev/null +++ b/lld/test/elf/Mips/validate-rel-03.test @@ -0,0 +1,56 @@ +# Check that the linker does not accept R_MIPS_CALL16 relocation +# against local symbol. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t.o +# RUN: not lld -flavor gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \ +# RUN: | FileCheck %s + +# CHECK: R_MIPS_CALL16 (11) relocation cannot be used against local symbol L0 in file {{.*}}validate-rel-03.test.tmp.o + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 16 + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 8 + Symbol: T0 + Type: R_MIPS_CALL16 + - Offset: 4 + Symbol: L0 + Type: R_MIPS_CALL16 + +Symbols: + Local: + - Name: L0 + Type: STT_FUNC + Section: .text + Value: 0 + Size: 4 + Global: + - Name: T0 + Type: STT_FUNC + Section: .text + Value: 4 + Size: 4 + - Name: T1 + Type: STT_FUNC + Section: .text + Value: 8 + Size: 8 +...