summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPete Cooper <peter_cooper@apple.com>2016-02-06 00:51:16 +0000
committerPete Cooper <peter_cooper@apple.com>2016-02-06 00:51:16 +0000
commitb8fec3ea626863a71e217c0ea75a74f8451a651c (patch)
treed8c1cb60fc3db02c750b9992b474e9428cc9a5a5
parentdc1414b3f950cb389775b634706a6635535ed825 (diff)
downloadbcm5719-llvm-b8fec3ea626863a71e217c0ea75a74f8451a651c.tar.gz
bcm5719-llvm-b8fec3ea626863a71e217c0ea75a74f8451a651c.zip
Set max segment protection level.
The initial segment protection was also being used to set the maximum segment protection level. Instead, the maximum should be set according to the architecture we are linking. For example on Mac OS it should be RWX on most pages, but on iOS is often on R_X. rdar://problem/24515136 llvm-svn: 259966
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFile.h3
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp12
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp43
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp9
-rw-r--r--lld/test/mach-o/seg-protection-arm64.yaml78
-rw-r--r--lld/test/mach-o/seg-protection-x86_64.yaml78
6 files changed, 205 insertions, 18 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
index 6dab8babe65..e01d72cc94d 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
@@ -172,7 +172,8 @@ struct Segment {
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
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index 8a11a5c7bac..b57afc0180e 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -570,7 +570,7 @@ void MachOFileLayout::buildFileOffsets() {
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
@@ -578,7 +578,7 @@ void MachOFileLayout::buildFileOffsets() {
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;
@@ -711,8 +711,8 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
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)
@@ -731,8 +731,8 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
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)
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 684c535a913..73f4e146906 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -92,13 +92,15 @@ struct SegmentInfo {
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 {
@@ -432,12 +434,38 @@ SegmentInfo *Util::segmentForName(StringRef segName) {
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;
}
@@ -589,7 +617,8 @@ void Util::copySegmentInfo(NormalizedFile &file) {
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);
}
}
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
index c795a72530a..5ae9204f72b 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
@@ -504,10 +504,11 @@ struct ScalarTraits<VMProtect> {
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);
}
};
diff --git a/lld/test/mach-o/seg-protection-arm64.yaml b/lld/test/mach-o/seg-protection-arm64.yaml
new file mode 100644
index 00000000000..f63b33ad2dc
--- /dev/null
+++ b/lld/test/mach-o/seg-protection-arm64.yaml
@@ -0,0 +1,78 @@
+# 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)
diff --git a/lld/test/mach-o/seg-protection-x86_64.yaml b/lld/test/mach-o/seg-protection-x86_64.yaml
new file mode 100644
index 00000000000..474f72f4c57
--- /dev/null
+++ b/lld/test/mach-o/seg-protection-x86_64.yaml
@@ -0,0 +1,78 @@
+# 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)
OpenPOWER on IntegriCloud