StringRef name;
Hex64 address;
Hex64 size;
- VMProtect access;
+ VMProtect init_access;
+ VMProtect max_access;
};
/// Only used in normalized final linked images to specify on which dylibs
llvm::dbgs() << "buildFileOffsets()\n");
for (const Segment &sg : _file.segments) {
_segInfo[&sg].fileOffset = fileOffset;
- if ((_seg1addr == INT64_MAX) && sg.access)
+ if ((_seg1addr == INT64_MAX) && sg.init_access)
_seg1addr = sg.address;
DEBUG_WITH_TYPE("MachOFileLayout",
llvm::dbgs() << " segment=" << sg.name
uint32_t segFileSize = 0;
// A segment that is not zero-fill must use a least one page of disk space.
- if (sg.access)
+ if (sg.init_access)
segFileSize = _file.pageSize;
for (const Section *s : _segInfo[&sg].sections) {
uint32_t sectOffset = s->address - sg.address;
cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
cmd->fileoff = _startOfLinkEdit;
cmd->filesize = linkeditSize;
- cmd->initprot = seg.access;
- cmd->maxprot = seg.access;
+ cmd->initprot = seg.init_access;
+ cmd->maxprot = seg.max_access;
cmd->nsects = 0;
cmd->flags = 0;
if (_swap)
cmd->vmsize = seg.size;
cmd->fileoff = segInfo.fileOffset;
cmd->filesize = segInfo.fileSize;
- cmd->maxprot = seg.access;
- cmd->initprot = seg.access;
+ cmd->initprot = seg.init_access;
+ cmd->maxprot = seg.max_access;
cmd->nsects = segInfo.sections.size();
cmd->flags = 0;
if (_swap)
StringRef name;
uint64_t address;
uint64_t size;
- uint32_t access;
+ uint32_t init_access;
+ uint32_t max_access;
std::vector<SectionInfo*> sections;
uint32_t normalizedSegmentIndex;
};
SegmentInfo::SegmentInfo(StringRef n)
- : name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) {
+ : name(n), address(0), size(0), init_access(0), max_access(0),
+ normalizedSegmentIndex(0) {
}
class Util {
return si;
}
auto *info = new (_allocator) SegmentInfo(segName);
+
+ // Set the initial segment protection.
if (segName.equals("__TEXT"))
- info->access = VM_PROT_READ | VM_PROT_EXECUTE;
- else if (segName.equals("__DATA"))
- info->access = VM_PROT_READ | VM_PROT_WRITE;
+ info->init_access = VM_PROT_READ | VM_PROT_EXECUTE;
else if (segName.equals("__PAGEZERO"))
- info->access = 0;
+ info->init_access = 0;
+ else if (segName.equals("__LINKEDIT"))
+ info->init_access = VM_PROT_READ;
+ else {
+ // All others default to read-write
+ info->init_access = VM_PROT_READ | VM_PROT_WRITE;
+ }
+
+ // Set max segment protection
+ // Note, its overkill to use a switch statement here, but makes it so much
+ // easier to use switch coverage to catch new cases.
+ switch (_ctx.os()) {
+ case lld::MachOLinkingContext::OS::unknown:
+ case lld::MachOLinkingContext::OS::macOSX:
+ case lld::MachOLinkingContext::OS::iOS_simulator:
+ if (segName.equals("__PAGEZERO")) {
+ info->max_access = 0;
+ break;
+ }
+ // All others default to all
+ info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
+ break;
+ case lld::MachOLinkingContext::OS::iOS:
+ // iPhoneOS always uses same protection for max and initial
+ info->max_access = info->init_access;
+ break;
+ }
_segmentInfos.push_back(info);
return info;
}
seg.name = sgi->name;
seg.address = sgi->address;
seg.size = sgi->size;
- seg.access = sgi->access;
+ seg.init_access = sgi->init_access;
+ seg.max_access = sgi->max_access;
file.segments.push_back(seg);
}
}
template <>
struct MappingTraits<Segment> {
static void mapping(IO &io, Segment& seg) {
- io.mapRequired("name", seg.name);
- io.mapRequired("address", seg.address);
- io.mapRequired("size", seg.size);
- io.mapRequired("access", seg.access);
+ io.mapRequired("name", seg.name);
+ io.mapRequired("address", seg.address);
+ io.mapRequired("size", seg.size);
+ io.mapRequired("init-access", seg.init_access);
+ io.mapRequired("max-access", seg.max_access);
}
};
--- /dev/null
+# RUN: lld -flavor darwin -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s
+
+--- !mach-o
+arch: arm64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: start
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+
+...
+
+# CHECK: Load command 0
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __PAGEZERO
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot ---
+# CHECK: initprot ---
+# CHECK: nsects 0
+# CHECK: flags (none)
+# CHECK: Load command 1
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 152
+# CHECK: segname __TEXT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot r-x
+# CHECK: initprot r-x
+# CHECK: nsects 1
+# CHECK: flags (none)
+# CHECK: Section
+# CHECK: sectname __text
+# CHECK: segname __TEXT
+# CHECK: addr
+# CHECK: size
+# CHECK: offset
+# CHECK: align 2^0 (1)
+# CHECK: reloff 0
+# CHECK: nreloc 0
+# CHECK: type S_REGULAR
+# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
+# CHECK: reserved1 0
+# CHECK: reserved2 0
+# CHECK: Load command 2
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __LINKEDIT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot r--
+# CHECK: initprot r--
+# CHECK: nsects 0
+# CHECK: flags (none)
--- /dev/null
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: start
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+
+...
+
+# CHECK: Load command 0
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __PAGEZERO
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot ---
+# CHECK: initprot ---
+# CHECK: nsects 0
+# CHECK: flags (none)
+# CHECK: Load command 1
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 152
+# CHECK: segname __TEXT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot rwx
+# CHECK: initprot r-x
+# CHECK: nsects 1
+# CHECK: flags (none)
+# CHECK: Section
+# CHECK: sectname __text
+# CHECK: segname __TEXT
+# CHECK: addr
+# CHECK: size
+# CHECK: offset
+# CHECK: align 2^0 (1)
+# CHECK: reloff 0
+# CHECK: nreloc 0
+# CHECK: type S_REGULAR
+# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
+# CHECK: reserved1 0
+# CHECK: reserved2 0
+# CHECK: Load command 2
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __LINKEDIT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot rwx
+# CHECK: initprot r--
+# CHECK: nsects 0
+# CHECK: flags (none)