Index: ELF/OutputSections.h
===================================================================
--- ELF/OutputSections.h
+++ ELF/OutputSections.h
@@ -279,10 +279,12 @@
   typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
   OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
   void addSection(InputSectionBase<ELFT> *C) override;
-  void sortByPriority();
+  void sortInitFini();
+  void sortCtorsDtors();
   void writeTo(uint8_t *Buf) override;
 
 private:
+  void reassignOffsets();
   std::vector<InputSection<ELFT> *> Sections;
 };
 
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -763,10 +763,25 @@
   return V;
 }
 
+// This function is called after we sort input sections
+// to update their offsets.
+template <class ELFT> void OutputSection<ELFT>::reassignOffsets() {
+  uintX_t Off = 0;
+  for (InputSection<ELFT> *S : Sections) {
+    Off = alignTo(Off, S->getAlign());
+    S->OutSecOff = Off;
+    Off += S->getSize();
+  }
+  this->Header.sh_size = Off;
+}
+
 // Sorts input sections by section name suffixes, so that .foo.N comes
 // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
+// We want to keep the original order if the priorities are the same
+// because the compiler keeps the original initialization order in a
+// translation unit and we need to respect that.
 // For more detail, read the section of the GCC's manual about init_priority.
-template <class ELFT> void OutputSection<ELFT>::sortByPriority() {
+template <class ELFT> void OutputSection<ELFT>::sortInitFini() {
   // Sort sections by priority.
   typedef std::pair<int, InputSection<ELFT> *> Pair;
   auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
@@ -778,15 +793,59 @@
   Sections.clear();
   for (Pair &P : V)
     Sections.push_back(P.second);
+  reassignOffsets();
+}
 
-  // Reassign section addresses.
-  uintX_t Off = 0;
-  for (InputSection<ELFT> *S : Sections) {
-    Off = alignTo(Off, S->getAlign());
-    S->OutSecOff = Off;
-    Off += S->getSize();
-  }
-  this->Header.sh_size = Off;
+// Returns true if S matches /crtbegin.?\.o$/.
+static bool isCrtbegin(StringRef S) {
+  if (S.endswith("crtbegin.o"))
+    return true;
+  // Drop ?.o from end and check if it ends with "crtbegin".
+  if (!S.endswith(".o") || S.size() < 3)
+    return false;
+  return S.drop_back(3).endswith("crtbegin");
+}
+
+// .ctors and .dtors are sorted by this priority from highest to lowest.
+//
+//  1. The section was contained in a CRT file. (crtbegin contains
+//     some sentinel value in its .ctors and .dtors so that the runtime
+//     can find the beginning of the sections.)
+//
+//  2. The section has an optional priority value in the form of ".ctors.N"
+//     or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
+//     they are compared as string rather than number.
+//
+//  3. The section is just ".ctors" or ".dtors".
+//
+// In an ideal world, we don't need this function because .init_array and
+// .ctors are duplicate features (and .init_array is newer.) However, there
+// are too many real-world use cases of .ctors, so we had no choice to
+// support that with this rather ad-hoc semantics.
+template <class ELFT>
+static bool compCtors(const InputSection<ELFT> *A,
+                      const InputSection<ELFT> *B) {
+  bool CrtA = isCrtbegin(A->getFile()->getName());
+  bool CrtB = isCrtbegin(B->getFile()->getName());
+  if (CrtA != CrtB)
+    return CrtA;
+  StringRef X = A->getSectionName();
+  StringRef Y = B->getSectionName();
+  assert(X.startswith(".ctors") || X.startswith(".dtors"));
+  assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
+  X = X.substr(6);
+  Y = Y.substr(6);
+  if (X.empty() || Y.empty())
+    return Y.empty();
+  return X < Y;
+}
+
+// Sorts input sections by the special rules for .ctors and .dtors.
+// Unfortunately the rules are different from the one for .{init,fini}_array.
+// Read the comment above.
+template <class ELFT> void OutputSection<ELFT>::sortCtorsDtors() {
+  std::stable_sort(Sections.begin(), Sections.end(), compCtors<ELFT>);
+  reassignOffsets();
 }
 
 // Returns a VA which a relocatin RI refers to. Used only for local symbols.
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -911,9 +911,15 @@
 
 // Sort input sections by section name suffixes for
 // __attribute__((init_priority(N))).
-template <class ELFT> static void sortByPriority(OutputSectionBase<ELFT> *S) {
+template <class ELFT> static void sortInitFini(OutputSectionBase<ELFT> *S) {
   if (S)
-    reinterpret_cast<OutputSection<ELFT> *>(S)->sortByPriority();
+    reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini();
+}
+
+// Sort input sections by the special rule for .ctors and .dtors.
+template <class ELFT> static void sortCtorsDtors(OutputSectionBase<ELFT> *S) {
+  if (S)
+    reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
 }
 
 // Create output section objects and add them to OutputSections.
@@ -964,10 +970,10 @@
       Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC);
 
   // Sort section contents for __attribute__((init_priority(N)).
-  sortByPriority(Out<ELFT>::Dynamic->InitArraySec);
-  sortByPriority(Out<ELFT>::Dynamic->FiniArraySec);
-  sortByPriority(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
-  sortByPriority(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
+  sortInitFini(Out<ELFT>::Dynamic->InitArraySec);
+  sortInitFini(Out<ELFT>::Dynamic->FiniArraySec);
+  sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
+  sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
 
   // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
   // symbols for sections, so that the runtime can get the start and end
Index: test/ELF/Inputs/ctors_dtors_priority.s
===================================================================
--- /dev/null
+++ test/ELF/Inputs/ctors_dtors_priority.s
@@ -0,0 +1,5 @@
+.section .ctors, "aw", @progbits
+  .byte 0xAA
+
+.section .dtors, "aw", @progbits
+  .byte 0xBB
Index: test/ELF/ctors_dtors_priority.s
===================================================================
--- test/ELF/ctors_dtors_priority.s
+++ test/ELF/ctors_dtors_priority.s
@@ -1,5 +1,8 @@
-// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-// RUN: ld.lld %t -o %t.exe
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN:   %p/Inputs/ctors_dtors_priority.s -o %t2
+// RUN: cp %t2 %t-crtbegin.o
+// RUN: ld.lld %t1 %t2 %t-crtbegin.o -o %t.exe
 // RUN: llvm-objdump -s %t.exe | FileCheck %s
 // REQUIRES: x86
 
@@ -12,7 +15,7 @@
   .byte 1
 .section .ctors.100, "aw", @progbits
   .long 2
-.section .ctors.5, "aw", @progbits
+.section .ctors.005, "aw", @progbits
   .byte 3
 .section .ctors, "aw", @progbits
   .byte 4
@@ -24,7 +27,7 @@
   .byte 0x11
 .section .dtors.100, "aw", @progbits
   .long 0x12
-.section .dtors.5, "aw", @progbits
+.section .dtors.005, "aw", @progbits
   .byte 0x13
 .section .dtors, "aw", @progbits
   .byte 0x14
@@ -32,6 +35,6 @@
   .byte 0x15
 
 // CHECK:      Contents of section .ctors:
-// CHECK-NEXT: 03020000 00000000 010405
+// CHECK-NEXT: aa030200 0000aa00 010405
 // CHECK:      Contents of section .dtors:
-// CHECK-NEXT: 13120000 00000000 111415
+// CHECK-NEXT: bb131200 0000bb00 111415