Index: lld/MachO/OutputSegment.h =================================================================== --- lld/MachO/OutputSegment.h +++ lld/MachO/OutputSegment.h @@ -55,6 +55,7 @@ StringRef name; uint32_t maxProt = 0; uint32_t initProt = 0; + uint32_t flags = 0; uint8_t index; llvm::TinyPtrVector segmentStartSymbols; Index: lld/MachO/OutputSegment.cpp =================================================================== --- lld/MachO/OutputSegment.cpp +++ lld/MachO/OutputSegment.cpp @@ -44,6 +44,10 @@ return initProt(name); } +static uint32_t flags(StringRef name) { + return name == segment_names::dataConst ? SG_READ_ONLY : 0; +} + size_t OutputSegment::numNonHiddenSections() const { size_t count = 0; for (const OutputSection *osec : sections) @@ -185,6 +189,7 @@ segRef->name = name; segRef->maxProt = maxProt(name); segRef->initProt = initProt(name); + segRef->flags = flags(name); outputSegments.push_back(segRef); return segRef; Index: lld/MachO/Writer.cpp =================================================================== --- lld/MachO/Writer.cpp +++ lld/MachO/Writer.cpp @@ -246,6 +246,7 @@ c->vmsize = seg->vmSize; c->filesize = seg->fileSize; c->nsects = seg->numNonHiddenSections(); + c->flags = seg->flags; for (const OutputSection *osec : seg->getSections()) { if (osec->isHidden()) Index: lld/test/MachO/builtin-rename.s =================================================================== --- lld/test/MachO/builtin-rename.s +++ lld/test/MachO/builtin-rename.s @@ -53,6 +53,23 @@ # YDATA-DAG: __DATA_CONST,__objc_protolist __DATA__objc_protolist # YDATA-DAG: __DATA_CONST,__nl_symbol_ptr __IMPORT__pointers +## Check that the SG_READ_ONLY flag is set on __DATA_CONST. +# RUN: llvm-otool -v -l %t/ydata | \ +# RUN: FileCheck %s --check-prefix=FLAGS + +# FLAGS-LABEL: Load command 2 +# FLAGS-NEXT: cmd LC_SEGMENT_64 +# FLAGS-NEXT: cmdsize +# FLAGS-NEXT: segname __DATA_CONST +# FLAGS-NEXT: vmaddr +# FLAGS-NEXT: vmsize +# FLAGS-NEXT: fileoff +# FLAGS-NEXT: filesize +# FLAGS-NEXT: maxprot rw- +# FLAGS-NEXT: initprot rw- +# FLAGS-NEXT: nsects 13 +# FLAGS-NEXT: flags SG_READ_ONLY + ## LLD doesn't support defining symbols in synthetic sections, so we test them ## via this slightly more awkward route. # RUN: llvm-readobj --section-headers %t/ydata | \ Index: llvm/include/llvm/BinaryFormat/MachO.h =================================================================== --- llvm/include/llvm/BinaryFormat/MachO.h +++ llvm/include/llvm/BinaryFormat/MachO.h @@ -107,6 +107,7 @@ SG_FVMLIB = 0x2u, SG_NORELOC = 0x4u, SG_PROTECTED_VERSION_1 = 0x8u, + SG_READ_ONLY = 0x10u, // Constant masks for the "flags" field in llvm::MachO::section and // llvm::MachO::section_64 Index: llvm/tools/llvm-objdump/MachODump.cpp =================================================================== --- llvm/tools/llvm-objdump/MachODump.cpp +++ llvm/tools/llvm-objdump/MachODump.cpp @@ -8858,6 +8858,11 @@ outs() << " PROTECTED_VERSION_1"; flags &= ~MachO::SG_PROTECTED_VERSION_1; } + if (flags & MachO::SG_READ_ONLY) { + // Note: Apple's otool has this inconsistency as well. + outs() << " SG_READ_ONLY"; + flags &= ~MachO::SG_READ_ONLY; + } if (flags) outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; else