Index: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -62,6 +62,21 @@ 0x00, 0x00 // nop }; +// Determine proper names for mapping symbols. +static std::string getMappingAtomName(DefinedAtom::CodeModel model, + const std::string &part) { + switch (model) { + case DefinedAtom::codeARM_a: + return part.empty() ? "$a" : "$a." + part; + case DefinedAtom::codeARM_d: + return part.empty() ? "$d" : "$d." + part; + case DefinedAtom::codeARM_t: + return part.empty() ? "$t" : "$t." + part; + default: + llvm_unreachable("Wrong code model of mapping atom"); + } +} + /// \brief Atoms that hold veneer code. class VeneerAtom : public SimpleELFDefinedAtom { StringRef _section; @@ -141,23 +156,62 @@ ARMGOTPLTAtom(const File &f) : ARMGOTAtom(f, ".got.plt") {} }; +/// \brief PLT entry atom. +/// Serves as a mapping symbol in the release mode. class ARMPLTAtom : public PLTAtom { public: - ARMPLTAtom(const File &f) : PLTAtom(f, ".plt") {} + ARMPLTAtom(const File &f, const std::string &name) + : PLTAtom(f, ".plt") { +#ifndef NDEBUG + _name = name; +#else + // Don't move the code to any base classes since + // virtual codeModel method would return wrong value. + _name = getMappingAtomName(codeModel(), name); +#endif + } + + DefinedAtom::CodeModel codeModel() const override { +#ifndef NDEBUG + return DefinedAtom::codeNA; +#else + return DefinedAtom::codeARM_a; +#endif + } ArrayRef rawContent() const override { return llvm::makeArrayRef(ARMPltAtomContent); } Alignment alignment() const override { return 4; } + + StringRef name() const override { return _name; } + +private: + std::string _name; }; +/// \brief Veneer atom for PLT entry. +/// Serves as a mapping symbol in the release mode. class ARMPLTVeneerAtom : public PLTAtom { public: - ARMPLTVeneerAtom(const File &f) : PLTAtom(f, ".plt") {} + ARMPLTVeneerAtom(const File &f, const std::string &name) + : PLTAtom(f, ".plt") { +#ifndef NDEBUG + _name = name; +#else + // Don't move the code to any base classes since + // virtual codeModel method would return wrong value. + _name = getMappingAtomName(codeModel(), name); +#endif + } DefinedAtom::CodeModel codeModel() const override { +#ifndef NDEBUG return DefinedAtom::codeARMThumb; +#else + return DefinedAtom::codeARM_t; +#endif } ArrayRef rawContent() const override { @@ -165,6 +219,11 @@ } Alignment alignment() const override { return 4; } + + StringRef name() const override { return _name; } + +private: + std::string _name; }; class ELFPassFile : public SimpleFile { @@ -295,14 +354,14 @@ /// \brief get a veneer for a PLT entry. const PLTAtom *getPLTVeneer(const DefinedAtom *da, PLTAtom *pa, StringRef source) { - auto va = new (_file._alloc) ARMPLTVeneerAtom(_file); + std::string name = "__plt_from_thumb"; + name += source; + name += da->name(); + // Create veneer for PLT entry. + auto va = new (_file._alloc) ARMPLTVeneerAtom(_file, name); // Fake reference to show connection between veneer and PLT entry. va->addReferenceELF_ARM(R_ARM_NONE, 0, pa, 0); -#ifndef NDEBUG - va->_name = "__plt_from_thumb"; - va->_name += source; - va->_name += da->name(); -#endif + _pltAtoms[da] = PLTWithVeneer(pa, va); return va; } @@ -335,16 +394,15 @@ assert(ga->customSectionName() == ".got.plt" && "GOT entry should be in a special section"); + std::string name = "__plt"; + name += source; + name += da->name(); // Create PLT entry for the GOT entry. - auto pa = new (_file._alloc) ARMPLTAtom(_file); + auto pa = new (_file._alloc) ARMPLTAtom(_file, name); pa->addReferenceELF_ARM(R_ARM_ALU_PC_G0_NC, 0, ga, -8); pa->addReferenceELF_ARM(R_ARM_ALU_PC_G1_NC, 4, ga, -4); pa->addReferenceELF_ARM(R_ARM_LDR_PC_G2, 8, ga, 0); -#ifndef NDEBUG - pa->_name = "__plt"; - pa->_name += source; - pa->_name += da->name(); -#endif + // Since all PLT entries are in ARM code, Thumb to ARM // switching should be added if the relocated place contais Thumb code. if (fromThumb) @@ -371,11 +429,7 @@ /// \brief get the PLT entry for a given IFUNC Atom. const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da, bool fromThumb) { - StringRef source; -#ifndef NDEBUG - source = "_ifunc_"; -#endif - return getPLTEntry(da, fromThumb, &Derived::createIFUNCGOTEntry, source); + return getPLTEntry(da, fromThumb, &Derived::createIFUNCGOTEntry, "_ifunc_"); } /// \brief Redirect the call to the PLT stub for the target IFUNC. Index: lld/trunk/test/elf/ARM/plt-mapping.test =================================================================== --- lld/trunk/test/elf/ARM/plt-mapping.test +++ lld/trunk/test/elf/ARM/plt-mapping.test @@ -0,0 +1,111 @@ +# Check that mapping symbols are properly generated for PLT entries. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o +# RUN: lld -flavor gnu -target arm-linux-gnu \ +# RUN: -Bstatic --noinhibit-exec %t-arm.o %t-thm.o -o %t +# RUN: llvm-readobj -symbols %t | FileCheck %s + +# CHECK: Name: {{[$]?[at]?[.]?}}__plt_ifunc_f1 +# CHECK: Name: {{[$]?[at]?[.]?}}__plt_from_thumb_ifunc_f2 +# CHECK: Name: {{[$]?[at]?[.]?}}__plt_ifunc_f2 + +# arm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: main + Type: R_ARM_MOVW_ABS_NC + - Offset: 0x000000000000000C + Symbol: main + Type: R_ARM_MOVT_ABS + - Offset: 0x0000000000000028 + Symbol: f1 + Type: R_ARM_CALL + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: f1 + Type: STT_GNU_IFUNC + Section: .text + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000020 + +# thm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEFF0346184680BD00BF + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: f + Type: R_ARM_THM_MOVW_ABS_NC + - Offset: 0x0000000000000008 + Symbol: f + Type: R_ARM_THM_MOVT_ABS + - Offset: 0x000000000000001C + Symbol: f2 + Type: R_ARM_THM_CALL + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: f2 + Type: STT_GNU_IFUNC + Section: .text + Value: 0x0000000000000001 + - Name: f + Type: STT_FUNC + Section: .text + Value: 0x0000000000000019 +...