Index: lib/ReaderWriter/ELF/CMakeLists.txt =================================================================== --- lib/ReaderWriter/ELF/CMakeLists.txt +++ lib/ReaderWriter/ELF/CMakeLists.txt @@ -1,5 +1,6 @@ add_lld_library(lldELF ArrayOrderPass.cpp + CtorsOrderPass.cpp ELFLinkingContext.cpp Reader.cpp Writer.cpp Index: lib/ReaderWriter/ELF/CtorsOrderPass.h =================================================================== --- /dev/null +++ lib/ReaderWriter/ELF/CtorsOrderPass.h @@ -0,0 +1,25 @@ +//===- lib/ReaderWriter/ELF/CtorsOrderPass.h ------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_CTORS_ORDER_PASS_H +#define LLD_READER_WRITER_ELF_CTORS_ORDER_PASS_H + +#include "lld/Core/Pass.h" + +namespace lld { +namespace elf { +/// \brief This pass sorts atoms in .{ctors,dtors}. sections. +class CtorsOrderPass : public Pass { +public: + void perform(std::unique_ptr &mergedFile) override; +}; +} +} + +#endif Index: lib/ReaderWriter/ELF/CtorsOrderPass.cpp =================================================================== --- /dev/null +++ lib/ReaderWriter/ELF/CtorsOrderPass.cpp @@ -0,0 +1,42 @@ +//===- lib/ReaderWriter/ELF/CtorsOrderPass.cpp ----------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CtorsOrderPass.h" + +#include + +namespace lld { +namespace elf { +void CtorsOrderPass::perform(std::unique_ptr &f) { + auto definedAtoms = f->definedAtoms(); + std::stable_sort(definedAtoms.begin(), definedAtoms.end(), + [](const DefinedAtom *left, const DefinedAtom *right) { + if (left->sectionChoice() != DefinedAtom::sectionCustomRequired || + right->sectionChoice() != DefinedAtom::sectionCustomRequired) + return false; + + StringRef leftSec = left->customSectionName(); + StringRef rightSec = right->customSectionName(); + + // Both sections start with the same prefixes. + if (!(leftSec.startswith(".ctors") && rightSec.startswith(".ctors")) && + !(leftSec.startswith(".dtors") && rightSec.startswith(".dtors"))) + return false; + + // Get priortiy + uint16_t leftPriority = 0; + leftSec.rsplit('.').second.getAsInteger(10, leftPriority); + uint16_t rightPriority = 0; + rightSec.rsplit('.').second.getAsInteger(10, rightPriority); + + return leftPriority < rightPriority; + }); +} +} // end namespace elf +} // end namespace lld Index: lib/ReaderWriter/ELF/DefaultLayout.h =================================================================== --- lib/ReaderWriter/ELF/DefaultLayout.h +++ lib/ReaderWriter/ELF/DefaultLayout.h @@ -351,6 +351,8 @@ return llvm::StringSwitch(name) .StartsWith(".init_array", ORDER_INIT_ARRAY) .StartsWith(".fini_array", ORDER_FINI_ARRAY) + .StartsWith(".ctors", ORDER_CTORS) + .StartsWith(".dtors", ORDER_DTORS) .Default(ORDER_DATA); case DefinedAtom::typeZeroFill: @@ -419,6 +421,8 @@ .StartsWith(".tbss", ".tbss") .StartsWith(".init_array", ".init_array") .StartsWith(".fini_array", ".fini_array") + .StartsWith(".ctors", ".ctors") + .StartsWith(".dtors", ".dtors") .Default(da->customSectionName()); } Index: lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -10,6 +10,7 @@ #include "lld/ReaderWriter/ELFLinkingContext.h" #include "ArrayOrderPass.h" +#include "CtorsOrderPass.h" #include "ELFFile.h" #include "TargetHandler.h" #include "Targets.h" @@ -72,6 +73,7 @@ if (_runLayoutPass) pm.add(std::unique_ptr(new LayoutPass(registry()))); pm.add(std::unique_ptr(new elf::ArrayOrderPass())); + pm.add(std::unique_ptr(new elf::CtorsOrderPass())); } uint16_t ELFLinkingContext::getOutputMachine() const { Index: test/elf/ctors-order.test =================================================================== --- /dev/null +++ test/elf/ctors-order.test @@ -0,0 +1,45 @@ +# RUN: yaml2obj -format=elf %s > %t +# RUN: lld -flavor gnu -target mipsel -shared %t --output-filetype=yaml \ +# RUN: | FileCheck %s + +# CHECK: defined-atoms: +# CHECK-NEXT: - type: data +# CHECK-NEXT: content: [ 11, 11, 11, 11 ] +# CHECK-NEXT: alignment: 2^2 +# CHECK-NEXT: section-choice: custom-required +# CHECK-NEXT: section-name: .ctors.1 +# CHECK-NEXT: - type: data +# CHECK-NEXT: content: [ 22, 22, 22, 22 ] +# CHECK-NEXT: alignment: 2^2 +# CHECK-NEXT: section-choice: custom-required +# CHECK-NEXT: section-name: .ctors.2 + +--- +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_32 ] +Sections: + - Name: .ctors.2 + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x04 + Content: '22222222' + - Name: .ctors.1 + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x04 + Content: '11111111' + +Symbols: + Local: + - Name: .ctors.2 + Type: STT_SECTION + Section: .ctors.2 + - Name: .ctors.1 + Type: STT_SECTION + Section: .ctors.1 +...