Skip to content

Commit 3f0b731

Browse files
BertalanDgiordano
authored andcommitted
[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 (cherry picked from commit f7b752d)
1 parent 8871c26 commit 3f0b731

File tree

6 files changed

+33
-0
lines changed

6 files changed

+33
-0
lines changed

lld/MachO/OutputSegment.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ static uint32_t maxProt(StringRef name) {
4444
return initProt(name);
4545
}
4646

47+
static uint32_t flags(StringRef name) {
48+
// If we ever implement shared cache output support, SG_READ_ONLY should not
49+
// be used for dylibs that can be placed in it.
50+
return name == segment_names::dataConst ? SG_READ_ONLY : 0;
51+
}
52+
4753
size_t OutputSegment::numNonHiddenSections() const {
4854
size_t count = 0;
4955
for (const OutputSection *osec : sections)
@@ -184,6 +190,7 @@ OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
184190
segRef->name = name;
185191
segRef->maxProt = maxProt(name);
186192
segRef->initProt = initProt(name);
193+
segRef->flags = flags(name);
187194

188195
outputSegments.push_back(segRef);
189196
return segRef;

lld/MachO/OutputSegment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class OutputSegment {
5656
StringRef name;
5757
uint32_t maxProt = 0;
5858
uint32_t initProt = 0;
59+
uint32_t flags = 0;
5960
uint8_t index;
6061

6162
llvm::TinyPtrVector<Defined *> segmentStartSymbols;

lld/MachO/Writer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ template <class LP> class LCSegment final : public LoadCommand {
246246
c->vmsize = seg->vmSize;
247247
c->filesize = seg->fileSize;
248248
c->nsects = seg->numNonHiddenSections();
249+
c->flags = seg->flags;
249250

250251
for (const OutputSection *osec : seg->getSections()) {
251252
if (osec->isHidden())

lld/test/MachO/builtin-rename.s

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,23 @@
5353
# YDATA-DAG: __DATA_CONST,__objc_protolist __DATA__objc_protolist
5454
# YDATA-DAG: __DATA_CONST,__nl_symbol_ptr __IMPORT__pointers
5555

56+
## Check that the SG_READ_ONLY flag is set on __DATA_CONST.
57+
# RUN: llvm-otool -v -l %t/ydata | \
58+
# RUN: FileCheck %s --check-prefix=FLAGS
59+
60+
# FLAGS-LABEL: Load command 2
61+
# FLAGS-NEXT: cmd LC_SEGMENT_64
62+
# FLAGS-NEXT: cmdsize
63+
# FLAGS-NEXT: segname __DATA_CONST
64+
# FLAGS-NEXT: vmaddr
65+
# FLAGS-NEXT: vmsize
66+
# FLAGS-NEXT: fileoff
67+
# FLAGS-NEXT: filesize
68+
# FLAGS-NEXT: maxprot rw-
69+
# FLAGS-NEXT: initprot rw-
70+
# FLAGS-NEXT: nsects 13
71+
# FLAGS-NEXT: flags SG_READ_ONLY
72+
5673
## LLD doesn't support defining symbols in synthetic sections, so we test them
5774
## via this slightly more awkward route.
5875
# RUN: llvm-readobj --section-headers %t/ydata | \

llvm/include/llvm/BinaryFormat/MachO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ enum : uint32_t {
106106
SG_FVMLIB = 0x2u,
107107
SG_NORELOC = 0x4u,
108108
SG_PROTECTED_VERSION_1 = 0x8u,
109+
SG_READ_ONLY = 0x10u,
109110

110111
// Constant masks for the "flags" field in llvm::MachO::section and
111112
// llvm::MachO::section_64

llvm/tools/llvm-objdump/MachODump.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8657,6 +8657,12 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
86578657
outs() << " PROTECTED_VERSION_1";
86588658
flags &= ~MachO::SG_PROTECTED_VERSION_1;
86598659
}
8660+
if (flags & MachO::SG_READ_ONLY) {
8661+
// Apple's otool prints the SG_ prefix for this flag, but not for the
8662+
// others.
8663+
outs() << " SG_READ_ONLY";
8664+
flags &= ~MachO::SG_READ_ONLY;
8665+
}
86608666
if (flags)
86618667
outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
86628668
else

0 commit comments

Comments
 (0)