diff --git a/lld/MachO/OutputSegment.cpp b/lld/MachO/OutputSegment.cpp --- a/lld/MachO/OutputSegment.cpp +++ b/lld/MachO/OutputSegment.cpp @@ -140,10 +140,15 @@ } void OutputSegment::sortOutputSections() { - llvm::sort(sections, compareByOrder(sectionOrder)); + // Must be stable_sort() to keep special sections such as + // S_THREAD_LOCAL_REGULAR in input order. + llvm::stable_sort(sections, compareByOrder(sectionOrder)); } void macho::sortOutputSegments() { + // sort() instead of stable_sort() is fine because segmentOrder() is + // name-based and getOrCreateOutputSegment() makes there's only a single + // segment for every name. llvm::sort(outputSegments, compareByOrder(segmentOrder)); } diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -79,7 +79,10 @@ LCUuid *uuidCommand = nullptr; OutputSegment *linkEditSegment = nullptr; - DenseMap concatOutputSections; + + // Output sections are added to output segments in iteration order + // of ConcatOutputSection, so must have deterministic iteration order. + MapVector concatOutputSections; }; // LC_DYLD_INFO_ONLY stores the offsets of symbol import/export information. diff --git a/lld/test/MachO/tlv-dylib.s b/lld/test/MachO/tlv-dylib.s --- a/lld/test/MachO/tlv-dylib.s +++ b/lld/test/MachO/tlv-dylib.s @@ -74,21 +74,21 @@ # FLAGS-NEXT: reloff 0 # FLAGS-NEXT: nreloc 0 # FLAGS-NEXT: type S_THREAD_LOCAL_ZEROFILL -# FLAGS: sectname __bss +# FLAGS: sectname __common # FLAGS-NEXT: segname __DATA # FLAGS-NEXT: addr -# FLAGS-NEXT: size 0x0000000000002000 +# FLAGS-NEXT: size 0x0000000000004000 # FLAGS-NEXT: offset 0 -# FLAGS-NEXT: align 2^0 (1) +# FLAGS-NEXT: align 2^14 (16384) # FLAGS-NEXT: reloff 0 # FLAGS-NEXT: nreloc 0 # FLAGS-NEXT: type S_ZEROFILL -# FLAGS: sectname __common +# FLAGS: sectname __bss # FLAGS-NEXT: segname __DATA # FLAGS-NEXT: addr -# FLAGS-NEXT: size 0x0000000000004000 +# FLAGS-NEXT: size 0x0000000000002000 # FLAGS-NEXT: offset 0 -# FLAGS-NEXT: align 2^14 (16384) +# FLAGS-NEXT: align 2^0 (1) # FLAGS-NEXT: reloff 0 # FLAGS-NEXT: nreloc 0 # FLAGS-NEXT: type S_ZEROFILL