diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index b89e7e444dd3..ee751fbe8b3f 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -236,12 +236,12 @@ public: si->doPreFlight(); } - inline bool findAtomAddrByName(StringRef name, uint64_t &addr) override { + inline const AtomLayout *findAtomLayoutByName(StringRef name) const override { for (auto sec : _sections) - if (auto section = dyn_cast >(sec)) - if (section->findAtomAddrByName(name, addr)) - return true; - return false; + if (auto section = dyn_cast>(sec)) + if (auto *al = section->findAtomLayoutByName(name)) + return al; + return nullptr; } inline void setHeader(ELFHeader *elfHeader) { _elfHeader = elfHeader; } diff --git a/lld/lib/ReaderWriter/ELF/Layout.h b/lld/lib/ReaderWriter/ELF/Layout.h index bb8cffe701db..e9c8f4072f54 100644 --- a/lld/lib/ReaderWriter/ELF/Layout.h +++ b/lld/lib/ReaderWriter/ELF/Layout.h @@ -41,8 +41,8 @@ public: /// \returns A reference to the atom layout or an error. The atom layout will /// be updated as linking progresses. virtual ErrorOr addAtom(const Atom *atom) = 0; - /// find the Atom Address in the current layout - virtual bool findAtomAddrByName(StringRef name, uint64_t &addr) = 0; + /// find the Atom in the current layout + virtual const AtomLayout *findAtomLayoutByName(StringRef name) const = 0; /// associates a section to a segment virtual void assignSectionsToSegments() = 0; /// associates a virtual address to the segment, section, and the atom diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h index eebb56e039d3..01aed1c6a709 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h @@ -32,12 +32,7 @@ protected: bool createImplicitFiles(std::vector> &) override; void finalizeDefaultAtomValues() override; - - std::error_code setELFHeader() override { - ExecutableWriter::setELFHeader(); - _writeHelper.setELFHeader(*this->_elfHeader); - return std::error_code(); - } + std::error_code setELFHeader() override; LLD_UNIQUE_BUMP_PTR(SymbolTable) createSymbolTable() override; LLD_UNIQUE_BUMP_PTR(DynamicTable) createDynamicTable() override; @@ -59,6 +54,25 @@ MipsExecutableWriter::MipsExecutableWriter( _writeHelper(ctx, layout, elfFlagsMerger), _mipsContext(ctx), _mipsTargetLayout(layout) {} +template +std::error_code MipsExecutableWriter::setELFHeader() { + std::error_code ec = ExecutableWriter::setELFHeader(); + if (ec) + return ec; + + StringRef entryName = _mipsContext.entrySymbolName(); + if (const AtomLayout *al = this->_layout.findAtomLayoutByName(entryName)) { + const auto *ea = cast(al->_atom); + if (ea->codeModel() == DefinedAtom::codeMipsMicro || + ea->codeModel() == DefinedAtom::codeMipsMicroPIC) + // Adjust entry symbol value if this symbol is microMIPS encoded. + this->_elfHeader->e_entry(al->_virtualAddr + 1); + } + + _writeHelper.setELFHeader(*this->_elfHeader); + return std::error_code(); +} + template void MipsExecutableWriter::buildDynamicSymbolTable(const File &file) { // MIPS ABI requires to add to dynsym even undefined symbols diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h index 2e6a88159b00..56965c604672 100644 --- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h @@ -428,9 +428,10 @@ template std::error_code OutputELFWriter::setELFHeader() { _elfHeader->e_shentsize(_shdrtab->entsize()); _elfHeader->e_shnum(_shdrtab->numHeaders()); _elfHeader->e_shstrndx(_shstrtab->ordinal()); - uint64_t virtualAddr = 0; - _layout.findAtomAddrByName(_context.entrySymbolName(), virtualAddr); - _elfHeader->e_entry(virtualAddr); + if (const auto *al = _layout.findAtomLayoutByName(_context.entrySymbolName())) + _elfHeader->e_entry(al->_virtualAddr); + else + _elfHeader->e_entry(0); return std::error_code(); } diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index 9c34deaadbe2..754ad1c9f95b 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -95,7 +95,9 @@ public: this->_segmentType = segmentType; } - virtual bool findAtomAddrByName(StringRef, uint64_t &) { return false; } + virtual const AtomLayout *findAtomLayoutByName(StringRef) const { + return nullptr; + } void setOutputSection(OutputSection *os, bool isFirst = false) { _outputSection = os; @@ -237,14 +239,11 @@ public: /// \brief Find the Atom address given a name, this is needed to properly /// apply relocation. The section class calls this to find the atom address /// to fix the relocation - virtual bool findAtomAddrByName(StringRef name, uint64_t &addr) { - for (auto ai : _atoms) { - if (ai->_atom->name() == name) { - addr = ai->_virtualAddr; - return true; - } - } - return false; + const AtomLayout *findAtomLayoutByName(StringRef name) const override { + for (auto ai : _atoms) + if (ai->_atom->name() == name) + return ai; + return nullptr; } /// \brief Return the raw flags, we need this to sort segments diff --git a/lld/test/elf/Mips/dynlib-fileheader-micro.test b/lld/test/elf/Mips/dynlib-fileheader-micro.test new file mode 100644 index 000000000000..139b3aa626c9 --- /dev/null +++ b/lld/test/elf/Mips/dynlib-fileheader-micro.test @@ -0,0 +1,82 @@ +# Check ELF Header for shared library in case of microMIPS symbols. + +# Build shared library +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o +# RUN: llvm-readobj -file-headers %t.so | FileCheck %s + +# CHECK: Format: ELF32-mips +# CHECK-NEXT: Arch: mipsel +# CHECK-NEXT: AddressSize: 32bit +# CHECK-NEXT: LoadName: +# CHECK-NEXT: ElfHeader { +# CHECK-NEXT: Ident { +# CHECK-NEXT: Magic: (7F 45 4C 46) +# CHECK-NEXT: Class: 32-bit (0x1) +# CHECK-NEXT: DataEncoding: LittleEndian (0x1) +# CHECK-NEXT: FileVersion: 1 +# CHECK-NEXT: OS/ABI: SystemV (0x0) +# CHECK-NEXT: ABIVersion: 0 +# CHECK-NEXT: Unused: (00 00 00 00 00 00 00) +# CHECK-NEXT: } +# CHECK-NEXT: Type: SharedObject (0x3) +# CHECK-NEXT: Machine: EM_MIPS (0x8) +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Entry: 0x100 +# CHECK-NEXT: ProgramHeaderOffset: 0x34 +# CHECK-NEXT: SectionHeaderOffset: 0x2100 +# CHECK-NEXT: Flags [ (0x72001007) +# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000) +# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000) +# CHECK-NEXT: EF_MIPS_CPIC (0x4) +# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000) +# CHECK-NEXT: EF_MIPS_NOREORDER (0x1) +# CHECK-NEXT: EF_MIPS_PIC (0x2) +# CHECK-NEXT: ] +# CHECK-NEXT: HeaderSize: 52 +# CHECK-NEXT: ProgramHeaderEntrySize: 32 +# CHECK-NEXT: ProgramHeaderCount: 4 +# CHECK-NEXT: SectionHeaderEntrySize: 40 +# CHECK-NEXT: SectionHeaderCount: 11 +# CHECK-NEXT: StringTableSectionIndex: 8 +# CHECK-NEXT:} + +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, + EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x04 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x04 + Size: 0x00 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x04 + Size: 0x00 + - Name: .reginfo + Type: SHT_MIPS_REGINFO + Flags: [ SHF_ALLOC ] + AddressAlign: 0x01 + Size: 0x18 + - Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x08 + Size: 0x18 + +Symbols: + Global: + - Name: glob + Section: .text + Other: [ STO_MIPS_MICROMIPS ] diff --git a/lld/test/elf/Mips/exe-fileheader-micro.test b/lld/test/elf/Mips/exe-fileheader-micro.test new file mode 100644 index 000000000000..351f299b04cd --- /dev/null +++ b/lld/test/elf/Mips/exe-fileheader-micro.test @@ -0,0 +1,69 @@ +# Check ELF Header for non-pic executable file in case +# of microMIPS entry symbol. + +# Build executable +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target mipsel -e glob -o %t.exe %t-o.o +# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s + +# CHECK: Format: ELF32-mips +# CHECK-NEXT: Arch: mipsel +# CHECK-NEXT: AddressSize: 32bit +# CHECK-NEXT: LoadName: +# CHECK-NEXT: ElfHeader { +# CHECK-NEXT: Ident { +# CHECK-NEXT: Magic: (7F 45 4C 46) +# CHECK-NEXT: Class: 32-bit (0x1) +# CHECK-NEXT: DataEncoding: LittleEndian (0x1) +# CHECK-NEXT: FileVersion: 1 +# CHECK-NEXT: OS/ABI: SystemV (0x0) +# CHECK-NEXT: ABIVersion: 0 +# CHECK-NEXT: Unused: (00 00 00 00 00 00 00) +# CHECK-NEXT: } +# CHECK-NEXT: Type: Executable (0x2) +# CHECK-NEXT: Machine: EM_MIPS (0x8) +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Entry: 0x400109 +# CHECK-NEXT: ProgramHeaderOffset: 0x34 +# CHECK-NEXT: SectionHeaderOffset: 0x1268 +# CHECK-NEXT: Flags [ (0x72001005) +# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000) +# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000) +# CHECK-NEXT: EF_MIPS_CPIC (0x4) +# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000) +# CHECK-NEXT: EF_MIPS_NOREORDER (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: HeaderSize: 52 +# CHECK-NEXT: ProgramHeaderEntrySize: 32 +# CHECK-NEXT: ProgramHeaderCount: 5 +# CHECK-NEXT: SectionHeaderEntrySize: 40 +# CHECK-NEXT: SectionHeaderCount: 11 +# CHECK-NEXT: StringTableSectionIndex: 8 +# CHECK-NEXT: } + +# o.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC, + EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Size: 0x08 + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + Global: + - Name: glob + Section: .text + Other: [ STO_MIPS_MICROMIPS ] +...