[lld-macho] Set the SG_READ_ONLY flag on __DATA_CONST

This flag instructs dyld to make the segment read-only after fixups have
been performed.

I'm not sure why this flag is needed, as on macOS 13 beta at least,
__DATA_CONST is read-only even without this flag; but ld64 sets it as
well.

Differential Revision: https://reviews.llvm.org/D133010
This commit is contained in:
Daniel Bertalan 2022-08-31 12:32:21 +02:00
parent eaede4b5b7
commit f7b752d277
No known key found for this signature in database
6 changed files with 33 additions and 0 deletions

View File

@ -44,6 +44,12 @@ static uint32_t maxProt(StringRef name) {
return initProt(name);
}
static uint32_t flags(StringRef name) {
// If we ever implement shared cache output support, SG_READ_ONLY should not
// be used for dylibs that can be placed in it.
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 +191,7 @@ OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
segRef->name = name;
segRef->maxProt = maxProt(name);
segRef->initProt = initProt(name);
segRef->flags = flags(name);
outputSegments.push_back(segRef);
return segRef;

View File

@ -55,6 +55,7 @@ public:
StringRef name;
uint32_t maxProt = 0;
uint32_t initProt = 0;
uint32_t flags = 0;
uint8_t index;
llvm::TinyPtrVector<Defined *> segmentStartSymbols;

View File

@ -246,6 +246,7 @@ public:
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())

View File

@ -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 | \

View File

@ -107,6 +107,7 @@ enum : uint32_t {
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

View File

@ -8858,6 +8858,12 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
outs() << " PROTECTED_VERSION_1";
flags &= ~MachO::SG_PROTECTED_VERSION_1;
}
if (flags & MachO::SG_READ_ONLY) {
// Apple's otool prints the SG_ prefix for this flag, but not for the
// others.
outs() << " SG_READ_ONLY";
flags &= ~MachO::SG_READ_ONLY;
}
if (flags)
outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
else