]> gcc.gnu.org Git - gcc.git/blame - gcc/config/host-darwin.cc
Update copyright years.
[gcc.git] / gcc / config / host-darwin.cc
CommitLineData
ed23bd30 1/* Darwin host-specific hook definitions.
aeee4812 2 Copyright (C) 2003-2023 Free Software Foundation, Inc.
ed23bd30
GK
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published
2f83c7d6 8 by the Free Software Foundation; either version 3, or (at your
ed23bd30
GK
9 option) any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
2f83c7d6
NC
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
ed23bd30
GK
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
22a98240 23#include "options.h"
718f9c0f 24#include "diagnostic-core.h"
ed23bd30 25#include "config/host-darwin.h"
22a98240
IS
26#include <errno.h>
27
28/* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the
29 binaries, the following VM addresses are expected to be available.
30 NOTE, that for aarch64, ASLR is always enabled - but the VM address
31 mentioned below is available (at least on Darwin20).
32
33 The spaces should all have 512Mb available c.f. PCH files for large
34 C++ or Objective-C in the range of 150Mb for 64b hosts.
35
0d5db1dd
IS
36 We also try to steer clear of places already used for sanitizers.
37
38 If the allocation fails at the 'ideal' address, we go with what the
39 kernel provides (there is more likelihood that we will need to relocate
40 on read in). */
22a98240
IS
41
42#define PAGE_SZ 4096
43#if defined(__x86_64) && defined(__LP64__)
44# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
22a98240
IS
45#elif defined(__x86_64)
46# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
22a98240
IS
47#elif defined(__i386)
48# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
22a98240
IS
49#elif defined(__POWERPC__) && defined(__LP64__)
50# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
22a98240
IS
51#elif defined(__POWERPC__)
52# define TRY_EMPTY_VM_SPACE 0x00006fe00000ULL
22a98240
IS
53#elif defined(__aarch64__)
54# undef PAGE_SZ
55# define PAGE_SZ 16384
56# define TRY_EMPTY_VM_SPACE 0x180000000000ULL
22a98240
IS
57#else
58# error "unknown Darwin target"
59#endif
60
61/* Try to map a known position in the VM. The current PCH implementation
62 can adjust values at write-time, but not at read-time thus we need to
63 pick up the same position when reading as we got at write-time. */
ed23bd30
GK
64
65void *
22a98240 66darwin_gt_pch_get_address (size_t sz, int fd)
ed23bd30 67{
0d5db1dd 68 /* First try with the constraint that we really want this address... */
22a98240
IS
69 void *addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
70 MAP_PRIVATE | MAP_FIXED, fd, 0);
71
72 if (addr != (void *) MAP_FAILED)
73 munmap (addr, sz);
74
75 /* This ought to be the only alternative to failure, but there are comments
76 that suggest some versions of mmap can be buggy and return a different
77 value. */
78 if (addr == (void *) TRY_EMPTY_VM_SPACE)
79 return addr;
80
22a98240
IS
81 /* OK try to find a space without the constraint. */
82 addr = mmap ((void *) TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
83 MAP_PRIVATE, fd, 0);
84
0d5db1dd
IS
85 /* We return whatever the kernel gave us. */
86 if (addr != (void *) MAP_FAILED)
22a98240 87 {
0d5db1dd
IS
88 /* Unmap the area before returning. */
89 munmap (addr, sz);
90 return addr;
22a98240
IS
91 }
92
0d5db1dd
IS
93 /* Otherwise, try again but put some arbitrary buffer space first. */
94 size_t buffer_size = 64 * 1024 * 1024;
22a98240
IS
95 void *buffer = mmap (0, buffer_size, PROT_NONE,
96 MAP_PRIVATE | MAP_ANON, -1, 0);
97 addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
98 MAP_PRIVATE, fd, 0);
0d5db1dd 99
22a98240
IS
100 if (buffer != (void *) MAP_FAILED)
101 munmap (buffer, buffer_size);
102
0d5db1dd
IS
103 /* If we failed this time, that means there is *no* large enough free
104 space. */
22a98240
IS
105 if (addr == (void *) MAP_FAILED)
106 {
34b45cc5 107 error ("PCH memory is not available: %m");
22a98240
IS
108 return NULL;
109 }
110
22a98240
IS
111 munmap (addr, sz);
112 return addr;
ed23bd30
GK
113}
114
22a98240
IS
115/* Try to mmap the PCH file at ADDR for SZ bytes at OFF offset in the file.
116 If we succeed return 1, if we cannot mmap the desired address, then we
117 fail with -1. */
ed23bd30
GK
118
119int
747380f4 120darwin_gt_pch_use_address (void *&addr, size_t sz, int fd, size_t off)
ed23bd30 121{
22a98240
IS
122 void *mapped_addr;
123
124 /* We're called with size == 0 if we're not planning to load a PCH
125 file at all. This allows the hook to free any static space that
126 we might have allocated at link time. */
127 if (sz == 0)
128 return -1;
ed23bd30 129
22a98240 130 gcc_checking_assert (!(off % PAGE_SZ));
ed23bd30 131
22a98240
IS
132 /* Try to map the file with MAP_PRIVATE and FIXED. */
133 mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
134 MAP_PRIVATE | MAP_FIXED, fd, (off_t) off);
ed23bd30 135
22a98240
IS
136 /* Hopefully, we succeed. */
137 if (mapped_addr == addr)
138 return 1;
ed23bd30 139
0d5db1dd
IS
140 /* In theory, the only alternative to success for MAP_FIXED should be FAILED
141 however, there are some buggy earlier implementations that could return
142 an address. */
22a98240
IS
143 if (mapped_addr != (void *) MAP_FAILED)
144 munmap (mapped_addr, sz);
145
0d5db1dd 146 /* Try to map the file with MAP_PRIVATE but let the kernel move it. */
22a98240 147 mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
0d5db1dd 148 MAP_PRIVATE, fd, (off_t) off);
22a98240 149
0d5db1dd
IS
150 /* Hopefully, we succeed. */
151 if (mapped_addr != (void *) MAP_FAILED)
ed23bd30 152 {
0d5db1dd
IS
153 addr = mapped_addr;
154 return 1;
22a98240
IS
155 }
156
0d5db1dd
IS
157 /* Try to make an anonymous private mmap at the desired location in case
158 the problem is in mapping the file. */
159 mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
160 MAP_PRIVATE | MAP_ANON, -1, (off_t)0);
161
162 /* If this fails, we are out of ideas (and maybe memory). */
163 if (mapped_addr == (void *) MAP_FAILED)
164 return -1;
165
166 addr = mapped_addr;
167
22a98240
IS
168 if (lseek (fd, off, SEEK_SET) == (off_t) -1)
169 return -1;
ed23bd30 170
22a98240
IS
171 while (sz)
172 {
173 ssize_t nbytes;
ed23bd30 174
bf15cd66 175 nbytes = read (fd, mapped_addr, MIN (sz, (size_t) -1 >> 1));
22a98240
IS
176 if (nbytes <= 0)
177 return -1;
bf15cd66 178 mapped_addr = (char *) mapped_addr + nbytes;
22a98240 179 sz -= nbytes;
ed23bd30
GK
180 }
181
22a98240 182 return 1;
ed23bd30 183}
This page took 4.735173 seconds and 5 git commands to generate.