authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-02 04:26:06+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-03 09:12:35+02:00
logc560e26fb7f7aee4f4a998970c1b7a73b3cae2ca
treeb2c7a8ca4b78019eeeaf004606449dbd9235c812
parent8ee52f99ceab6a05b931eeb48825c00fd26ac486
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.os.linux: Rename some arch bits files to match std.Target.Cpu.Arch tags.


8 files changed, 940 insertions(+), 940 deletions(-)

lib/std/os/linux.zig+3-3
...@@ -37,8 +37,8 @@ const syscall_bits = switch (native_arch) {...@@ -37,8 +37,8 @@ const syscall_bits = switch (native_arch) {
37const arch_bits = switch (native_arch) {37const arch_bits = switch (native_arch) {
38 .x86 => @import("linux/x86.zig"),38 .x86 => @import("linux/x86.zig"),
39 .x86_64 => @import("linux/x86_64.zig"),39 .x86_64 => @import("linux/x86_64.zig"),
40 .aarch64, .aarch64_be => @import("linux/arm64.zig"),40 .aarch64, .aarch64_be => @import("linux/aarch64.zig"),
41 .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),41 .arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"),
42 .riscv32 => @import("linux/riscv32.zig"),42 .riscv32 => @import("linux/riscv32.zig"),
43 .riscv64 => @import("linux/riscv64.zig"),43 .riscv64 => @import("linux/riscv64.zig"),
44 .sparc64 => @import("linux/sparc64.zig"),44 .sparc64 => @import("linux/sparc64.zig"),
...@@ -116,7 +116,7 @@ pub const user_desc = arch_bits.user_desc;...@@ -116,7 +116,7 @@ pub const user_desc = arch_bits.user_desc;
116pub const getcontext = arch_bits.getcontext;116pub const getcontext = arch_bits.getcontext;
117117
118pub const tls = @import("linux/tls.zig");118pub const tls = @import("linux/tls.zig");
119pub const pie = @import("linux/start_pie.zig");119pub const pie = @import("linux/pie.zig");
120pub const BPF = @import("linux/bpf.zig");120pub const BPF = @import("linux/bpf.zig");
121pub const IOCTL = @import("linux/ioctl.zig");121pub const IOCTL = @import("linux/ioctl.zig");
122pub const SECCOMP = @import("linux/seccomp.zig");122pub const SECCOMP = @import("linux/seccomp.zig");
lib/std/os/linux/aarch64.zig created+288
...@@ -0,0 +1,288 @@
1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
3const linux = std.os.linux;
4const SYS = linux.SYS;
5const socklen_t = linux.socklen_t;
6const sockaddr = linux.sockaddr;
7const iovec = std.posix.iovec;
8const iovec_const = std.posix.iovec_const;
9const uid_t = linux.uid_t;
10const gid_t = linux.gid_t;
11const pid_t = linux.pid_t;
12const stack_t = linux.stack_t;
13const sigset_t = linux.sigset_t;
14const timespec = std.os.linux.timespec;
15
16pub fn syscall0(number: SYS) usize {
17 return asm volatile ("svc #0"
18 : [ret] "={x0}" (-> usize),
19 : [number] "{x8}" (@intFromEnum(number)),
20 : "memory", "cc"
21 );
22}
23
24pub fn syscall1(number: SYS, arg1: usize) usize {
25 return asm volatile ("svc #0"
26 : [ret] "={x0}" (-> usize),
27 : [number] "{x8}" (@intFromEnum(number)),
28 [arg1] "{x0}" (arg1),
29 : "memory", "cc"
30 );
31}
32
33pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
34 return asm volatile ("svc #0"
35 : [ret] "={x0}" (-> usize),
36 : [number] "{x8}" (@intFromEnum(number)),
37 [arg1] "{x0}" (arg1),
38 [arg2] "{x1}" (arg2),
39 : "memory", "cc"
40 );
41}
42
43pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
44 return asm volatile ("svc #0"
45 : [ret] "={x0}" (-> usize),
46 : [number] "{x8}" (@intFromEnum(number)),
47 [arg1] "{x0}" (arg1),
48 [arg2] "{x1}" (arg2),
49 [arg3] "{x2}" (arg3),
50 : "memory", "cc"
51 );
52}
53
54pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
55 return asm volatile ("svc #0"
56 : [ret] "={x0}" (-> usize),
57 : [number] "{x8}" (@intFromEnum(number)),
58 [arg1] "{x0}" (arg1),
59 [arg2] "{x1}" (arg2),
60 [arg3] "{x2}" (arg3),
61 [arg4] "{x3}" (arg4),
62 : "memory", "cc"
63 );
64}
65
66pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
67 return asm volatile ("svc #0"
68 : [ret] "={x0}" (-> usize),
69 : [number] "{x8}" (@intFromEnum(number)),
70 [arg1] "{x0}" (arg1),
71 [arg2] "{x1}" (arg2),
72 [arg3] "{x2}" (arg3),
73 [arg4] "{x3}" (arg4),
74 [arg5] "{x4}" (arg5),
75 : "memory", "cc"
76 );
77}
78
79pub fn syscall6(
80 number: SYS,
81 arg1: usize,
82 arg2: usize,
83 arg3: usize,
84 arg4: usize,
85 arg5: usize,
86 arg6: usize,
87) usize {
88 return asm volatile ("svc #0"
89 : [ret] "={x0}" (-> usize),
90 : [number] "{x8}" (@intFromEnum(number)),
91 [arg1] "{x0}" (arg1),
92 [arg2] "{x1}" (arg2),
93 [arg3] "{x2}" (arg3),
94 [arg4] "{x3}" (arg4),
95 [arg5] "{x4}" (arg5),
96 [arg6] "{x5}" (arg6),
97 : "memory", "cc"
98 );
99}
100
101pub fn clone() callconv(.Naked) usize {
102 // __clone(func, stack, flags, arg, ptid, tls, ctid)
103 // x0, x1, w2, x3, x4, x5, x6
104 //
105 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106 // x8, x0, x1, x2, x3, x4
107 asm volatile (
108 \\ // align stack and save func,arg
109 \\ and x1,x1,#-16
110 \\ stp x0,x3,[x1,#-16]!
111 \\
112 \\ // syscall
113 \\ uxtw x0,w2
114 \\ mov x2,x4
115 \\ mov x3,x5
116 \\ mov x4,x6
117 \\ mov x8,#220 // SYS_clone
118 \\ svc #0
119 \\
120 \\ cbz x0,1f
121 \\ // parent
122 \\ ret
123 \\ // child
124 \\1: ldp x1,x0,[sp],#16
125 \\ blr x1
126 \\ mov x8,#93 // SYS_exit
127 \\ svc #0
128 );
129}
130
131pub const restore = restore_rt;
132
133pub fn restore_rt() callconv(.Naked) noreturn {
134 switch (@import("builtin").zig_backend) {
135 .stage2_c => asm volatile (
136 \\ mov x8, %[number]
137 \\ svc #0
138 :
139 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cc"
141 ),
142 else => asm volatile (
143 \\ svc #0
144 :
145 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
146 : "memory", "cc"
147 ),
148 }
149}
150
151pub const F = struct {
152 pub const DUPFD = 0;
153 pub const GETFD = 1;
154 pub const SETFD = 2;
155 pub const GETFL = 3;
156 pub const SETFL = 4;
157
158 pub const SETOWN = 8;
159 pub const GETOWN = 9;
160 pub const SETSIG = 10;
161 pub const GETSIG = 11;
162
163 pub const GETLK = 5;
164 pub const SETLK = 6;
165 pub const SETLKW = 7;
166
167 pub const RDLCK = 0;
168 pub const WRLCK = 1;
169 pub const UNLCK = 2;
170
171 pub const SETOWN_EX = 15;
172 pub const GETOWN_EX = 16;
173
174 pub const GETOWNER_UIDS = 17;
175};
176
177pub const VDSO = struct {
178 pub const CGT_SYM = "__kernel_clock_gettime";
179 pub const CGT_VER = "LINUX_2.6.39";
180};
181
182pub const Flock = extern struct {
183 type: i16,
184 whence: i16,
185 start: off_t,
186 len: off_t,
187 pid: pid_t,
188 __unused: [4]u8,
189};
190
191pub const msghdr = extern struct {
192 name: ?*sockaddr,
193 namelen: socklen_t,
194 iov: [*]iovec,
195 iovlen: i32,
196 __pad1: i32 = 0,
197 control: ?*anyopaque,
198 controllen: socklen_t,
199 __pad2: socklen_t = 0,
200 flags: i32,
201};
202
203pub const msghdr_const = extern struct {
204 name: ?*const sockaddr,
205 namelen: socklen_t,
206 iov: [*]const iovec_const,
207 iovlen: i32,
208 __pad1: i32 = 0,
209 control: ?*const anyopaque,
210 controllen: socklen_t,
211 __pad2: socklen_t = 0,
212 flags: i32,
213};
214
215pub const blksize_t = i32;
216pub const nlink_t = u32;
217pub const time_t = isize;
218pub const mode_t = u32;
219pub const off_t = isize;
220pub const ino_t = usize;
221pub const dev_t = usize;
222pub const blkcnt_t = isize;
223
224// The `stat` definition used by the Linux kernel.
225pub const Stat = extern struct {
226 dev: dev_t,
227 ino: ino_t,
228 mode: mode_t,
229 nlink: nlink_t,
230 uid: uid_t,
231 gid: gid_t,
232 rdev: dev_t,
233 __pad: usize,
234 size: off_t,
235 blksize: blksize_t,
236 __pad2: i32,
237 blocks: blkcnt_t,
238 atim: timespec,
239 mtim: timespec,
240 ctim: timespec,
241 __unused: [2]u32,
242
243 pub fn atime(self: @This()) timespec {
244 return self.atim;
245 }
246
247 pub fn mtime(self: @This()) timespec {
248 return self.mtim;
249 }
250
251 pub fn ctime(self: @This()) timespec {
252 return self.ctim;
253 }
254};
255
256pub const timeval = extern struct {
257 sec: isize,
258 usec: isize,
259};
260
261pub const timezone = extern struct {
262 minuteswest: i32,
263 dsttime: i32,
264};
265
266pub const mcontext_t = extern struct {
267 fault_address: usize,
268 regs: [31]usize,
269 sp: usize,
270 pc: usize,
271 pstate: usize,
272 // Make sure the field is correctly aligned since this area
273 // holds various FP/vector registers
274 reserved1: [256 * 16]u8 align(16),
275};
276
277pub const ucontext_t = extern struct {
278 flags: usize,
279 link: ?*ucontext_t,
280 stack: stack_t,
281 sigmask: sigset_t,
282 mcontext: mcontext_t,
283};
284
285/// TODO
286pub const getcontext = {};
287
288pub const Elf_Symndx = u32;
lib/std/os/linux/arm-eabi.zig deleted-344
...@@ -1,344 +0,0 @@
1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
3const linux = std.os.linux;
4const SYS = linux.SYS;
5const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;
7const socklen_t = linux.socklen_t;
8const stack_t = linux.stack_t;
9const sigset_t = linux.sigset_t;
10const uid_t = linux.uid_t;
11const gid_t = linux.gid_t;
12const pid_t = linux.pid_t;
13const sockaddr = linux.sockaddr;
14const timespec = linux.timespec;
15
16pub fn syscall0(number: SYS) usize {
17 return asm volatile ("svc #0"
18 : [ret] "={r0}" (-> usize),
19 : [number] "{r7}" (@intFromEnum(number)),
20 : "memory"
21 );
22}
23
24pub fn syscall1(number: SYS, arg1: usize) usize {
25 return asm volatile ("svc #0"
26 : [ret] "={r0}" (-> usize),
27 : [number] "{r7}" (@intFromEnum(number)),
28 [arg1] "{r0}" (arg1),
29 : "memory"
30 );
31}
32
33pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
34 return asm volatile ("svc #0"
35 : [ret] "={r0}" (-> usize),
36 : [number] "{r7}" (@intFromEnum(number)),
37 [arg1] "{r0}" (arg1),
38 [arg2] "{r1}" (arg2),
39 : "memory"
40 );
41}
42
43pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
44 return asm volatile ("svc #0"
45 : [ret] "={r0}" (-> usize),
46 : [number] "{r7}" (@intFromEnum(number)),
47 [arg1] "{r0}" (arg1),
48 [arg2] "{r1}" (arg2),
49 [arg3] "{r2}" (arg3),
50 : "memory"
51 );
52}
53
54pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
55 return asm volatile ("svc #0"
56 : [ret] "={r0}" (-> usize),
57 : [number] "{r7}" (@intFromEnum(number)),
58 [arg1] "{r0}" (arg1),
59 [arg2] "{r1}" (arg2),
60 [arg3] "{r2}" (arg3),
61 [arg4] "{r3}" (arg4),
62 : "memory"
63 );
64}
65
66pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
67 return asm volatile ("svc #0"
68 : [ret] "={r0}" (-> usize),
69 : [number] "{r7}" (@intFromEnum(number)),
70 [arg1] "{r0}" (arg1),
71 [arg2] "{r1}" (arg2),
72 [arg3] "{r2}" (arg3),
73 [arg4] "{r3}" (arg4),
74 [arg5] "{r4}" (arg5),
75 : "memory"
76 );
77}
78
79pub fn syscall6(
80 number: SYS,
81 arg1: usize,
82 arg2: usize,
83 arg3: usize,
84 arg4: usize,
85 arg5: usize,
86 arg6: usize,
87) usize {
88 return asm volatile ("svc #0"
89 : [ret] "={r0}" (-> usize),
90 : [number] "{r7}" (@intFromEnum(number)),
91 [arg1] "{r0}" (arg1),
92 [arg2] "{r1}" (arg2),
93 [arg3] "{r2}" (arg3),
94 [arg4] "{r3}" (arg4),
95 [arg5] "{r4}" (arg5),
96 [arg6] "{r5}" (arg6),
97 : "memory"
98 );
99}
100
101pub fn clone() callconv(.Naked) usize {
102 // __clone(func, stack, flags, arg, ptid, tls, ctid)
103 // r0, r1, r2, r3, +0, +4, +8
104 //
105 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106 // r7 r0, r1, r2, r3, r4
107 asm volatile (
108 \\ stmfd sp!,{r4,r5,r6,r7}
109 \\ mov r7,#120 // SYS_clone
110 \\ mov r6,r3
111 \\ mov r5,r0
112 \\ mov r0,r2
113 \\ and r1,r1,#-16
114 \\ ldr r2,[sp,#16]
115 \\ ldr r3,[sp,#20]
116 \\ ldr r4,[sp,#24]
117 \\ svc 0
118 \\ tst r0,r0
119 \\ beq 1f
120 \\ ldmfd sp!,{r4,r5,r6,r7}
121 \\ bx lr
122 \\
123 \\1: mov r0,r6
124 \\ bl 3f
125 \\2: mov r7,#1 // SYS_exit
126 \\ svc 0
127 \\ b 2b
128 \\3: bx r5
129 );
130}
131
132pub fn restore() callconv(.Naked) noreturn {
133 switch (@import("builtin").zig_backend) {
134 .stage2_c => asm volatile (
135 \\ mov r7, %[number]
136 \\ svc #0
137 :
138 : [number] "I" (@intFromEnum(SYS.sigreturn)),
139 : "memory"
140 ),
141 else => asm volatile (
142 \\ svc #0
143 :
144 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
145 : "memory"
146 ),
147 }
148}
149
150pub fn restore_rt() callconv(.Naked) noreturn {
151 switch (@import("builtin").zig_backend) {
152 .stage2_c => asm volatile (
153 \\ mov r7, %[number]
154 \\ svc #0
155 :
156 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
157 : "memory"
158 ),
159 else => asm volatile (
160 \\ svc #0
161 :
162 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
163 : "memory"
164 ),
165 }
166}
167
168pub const MMAP2_UNIT = 4096;
169
170pub const F = struct {
171 pub const DUPFD = 0;
172 pub const GETFD = 1;
173 pub const SETFD = 2;
174 pub const GETFL = 3;
175 pub const SETFL = 4;
176
177 pub const SETOWN = 8;
178 pub const GETOWN = 9;
179 pub const SETSIG = 10;
180 pub const GETSIG = 11;
181
182 pub const GETLK = 12;
183 pub const SETLK = 13;
184 pub const SETLKW = 14;
185
186 pub const RDLCK = 0;
187 pub const WRLCK = 1;
188 pub const UNLCK = 2;
189
190 pub const SETOWN_EX = 15;
191 pub const GETOWN_EX = 16;
192
193 pub const GETOWNER_UIDS = 17;
194};
195
196pub const VDSO = struct {
197 pub const CGT_SYM = "__vdso_clock_gettime";
198 pub const CGT_VER = "LINUX_2.6";
199};
200
201pub const HWCAP = struct {
202 pub const SWP = 1 << 0;
203 pub const HALF = 1 << 1;
204 pub const THUMB = 1 << 2;
205 pub const @"26BIT" = 1 << 3;
206 pub const FAST_MULT = 1 << 4;
207 pub const FPA = 1 << 5;
208 pub const VFP = 1 << 6;
209 pub const EDSP = 1 << 7;
210 pub const JAVA = 1 << 8;
211 pub const IWMMXT = 1 << 9;
212 pub const CRUNCH = 1 << 10;
213 pub const THUMBEE = 1 << 11;
214 pub const NEON = 1 << 12;
215 pub const VFPv3 = 1 << 13;
216 pub const VFPv3D16 = 1 << 14;
217 pub const TLS = 1 << 15;
218 pub const VFPv4 = 1 << 16;
219 pub const IDIVA = 1 << 17;
220 pub const IDIVT = 1 << 18;
221 pub const VFPD32 = 1 << 19;
222 pub const IDIV = IDIVA | IDIVT;
223 pub const LPAE = 1 << 20;
224 pub const EVTSTRM = 1 << 21;
225};
226
227pub const Flock = extern struct {
228 type: i16,
229 whence: i16,
230 __pad0: [4]u8,
231 start: off_t,
232 len: off_t,
233 pid: pid_t,
234 __unused: [4]u8,
235};
236
237pub const msghdr = extern struct {
238 name: ?*sockaddr,
239 namelen: socklen_t,
240 iov: [*]iovec,
241 iovlen: i32,
242 control: ?*anyopaque,
243 controllen: socklen_t,
244 flags: i32,
245};
246
247pub const msghdr_const = extern struct {
248 name: ?*const sockaddr,
249 namelen: socklen_t,
250 iov: [*]const iovec_const,
251 iovlen: i32,
252 control: ?*const anyopaque,
253 controllen: socklen_t,
254 flags: i32,
255};
256
257pub const blksize_t = i32;
258pub const nlink_t = u32;
259pub const time_t = isize;
260pub const mode_t = u32;
261pub const off_t = i64;
262pub const ino_t = u64;
263pub const dev_t = u64;
264pub const blkcnt_t = i64;
265
266// The `stat` definition used by the Linux kernel.
267pub const Stat = extern struct {
268 dev: dev_t,
269 __dev_padding: u32,
270 __ino_truncated: u32,
271 mode: mode_t,
272 nlink: nlink_t,
273 uid: uid_t,
274 gid: gid_t,
275 rdev: dev_t,
276 __rdev_padding: u32,
277 size: off_t,
278 blksize: blksize_t,
279 blocks: blkcnt_t,
280 atim: timespec,
281 mtim: timespec,
282 ctim: timespec,
283 ino: ino_t,
284
285 pub fn atime(self: @This()) timespec {
286 return self.atim;
287 }
288
289 pub fn mtime(self: @This()) timespec {
290 return self.mtim;
291 }
292
293 pub fn ctime(self: @This()) timespec {
294 return self.ctim;
295 }
296};
297
298pub const timeval = extern struct {
299 sec: i32,
300 usec: i32,
301};
302
303pub const timezone = extern struct {
304 minuteswest: i32,
305 dsttime: i32,
306};
307
308pub const mcontext_t = extern struct {
309 trap_no: usize,
310 error_code: usize,
311 oldmask: usize,
312 arm_r0: usize,
313 arm_r1: usize,
314 arm_r2: usize,
315 arm_r3: usize,
316 arm_r4: usize,
317 arm_r5: usize,
318 arm_r6: usize,
319 arm_r7: usize,
320 arm_r8: usize,
321 arm_r9: usize,
322 arm_r10: usize,
323 arm_fp: usize,
324 arm_ip: usize,
325 arm_sp: usize,
326 arm_lr: usize,
327 arm_pc: usize,
328 arm_cpsr: usize,
329 fault_address: usize,
330};
331
332pub const ucontext_t = extern struct {
333 flags: usize,
334 link: ?*ucontext_t,
335 stack: stack_t,
336 mcontext: mcontext_t,
337 sigmask: sigset_t,
338 regspace: [64]u64,
339};
340
341/// TODO
342pub const getcontext = {};
343
344pub const Elf_Symndx = u32;
lib/std/os/linux/arm.zig created+344
...@@ -0,0 +1,344 @@
1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
3const linux = std.os.linux;
4const SYS = linux.SYS;
5const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;
7const socklen_t = linux.socklen_t;
8const stack_t = linux.stack_t;
9const sigset_t = linux.sigset_t;
10const uid_t = linux.uid_t;
11const gid_t = linux.gid_t;
12const pid_t = linux.pid_t;
13const sockaddr = linux.sockaddr;
14const timespec = linux.timespec;
15
16pub fn syscall0(number: SYS) usize {
17 return asm volatile ("svc #0"
18 : [ret] "={r0}" (-> usize),
19 : [number] "{r7}" (@intFromEnum(number)),
20 : "memory"
21 );
22}
23
24pub fn syscall1(number: SYS, arg1: usize) usize {
25 return asm volatile ("svc #0"
26 : [ret] "={r0}" (-> usize),
27 : [number] "{r7}" (@intFromEnum(number)),
28 [arg1] "{r0}" (arg1),
29 : "memory"
30 );
31}
32
33pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
34 return asm volatile ("svc #0"
35 : [ret] "={r0}" (-> usize),
36 : [number] "{r7}" (@intFromEnum(number)),
37 [arg1] "{r0}" (arg1),
38 [arg2] "{r1}" (arg2),
39 : "memory"
40 );
41}
42
43pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
44 return asm volatile ("svc #0"
45 : [ret] "={r0}" (-> usize),
46 : [number] "{r7}" (@intFromEnum(number)),
47 [arg1] "{r0}" (arg1),
48 [arg2] "{r1}" (arg2),
49 [arg3] "{r2}" (arg3),
50 : "memory"
51 );
52}
53
54pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
55 return asm volatile ("svc #0"
56 : [ret] "={r0}" (-> usize),
57 : [number] "{r7}" (@intFromEnum(number)),
58 [arg1] "{r0}" (arg1),
59 [arg2] "{r1}" (arg2),
60 [arg3] "{r2}" (arg3),
61 [arg4] "{r3}" (arg4),
62 : "memory"
63 );
64}
65
66pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
67 return asm volatile ("svc #0"
68 : [ret] "={r0}" (-> usize),
69 : [number] "{r7}" (@intFromEnum(number)),
70 [arg1] "{r0}" (arg1),
71 [arg2] "{r1}" (arg2),
72 [arg3] "{r2}" (arg3),
73 [arg4] "{r3}" (arg4),
74 [arg5] "{r4}" (arg5),
75 : "memory"
76 );
77}
78
79pub fn syscall6(
80 number: SYS,
81 arg1: usize,
82 arg2: usize,
83 arg3: usize,
84 arg4: usize,
85 arg5: usize,
86 arg6: usize,
87) usize {
88 return asm volatile ("svc #0"
89 : [ret] "={r0}" (-> usize),
90 : [number] "{r7}" (@intFromEnum(number)),
91 [arg1] "{r0}" (arg1),
92 [arg2] "{r1}" (arg2),
93 [arg3] "{r2}" (arg3),
94 [arg4] "{r3}" (arg4),
95 [arg5] "{r4}" (arg5),
96 [arg6] "{r5}" (arg6),
97 : "memory"
98 );
99}
100
101pub fn clone() callconv(.Naked) usize {
102 // __clone(func, stack, flags, arg, ptid, tls, ctid)
103 // r0, r1, r2, r3, +0, +4, +8
104 //
105 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106 // r7 r0, r1, r2, r3, r4
107 asm volatile (
108 \\ stmfd sp!,{r4,r5,r6,r7}
109 \\ mov r7,#120 // SYS_clone
110 \\ mov r6,r3
111 \\ mov r5,r0
112 \\ mov r0,r2
113 \\ and r1,r1,#-16
114 \\ ldr r2,[sp,#16]
115 \\ ldr r3,[sp,#20]
116 \\ ldr r4,[sp,#24]
117 \\ svc 0
118 \\ tst r0,r0
119 \\ beq 1f
120 \\ ldmfd sp!,{r4,r5,r6,r7}
121 \\ bx lr
122 \\
123 \\1: mov r0,r6
124 \\ bl 3f
125 \\2: mov r7,#1 // SYS_exit
126 \\ svc 0
127 \\ b 2b
128 \\3: bx r5
129 );
130}
131
132pub fn restore() callconv(.Naked) noreturn {
133 switch (@import("builtin").zig_backend) {
134 .stage2_c => asm volatile (
135 \\ mov r7, %[number]
136 \\ svc #0
137 :
138 : [number] "I" (@intFromEnum(SYS.sigreturn)),
139 : "memory"
140 ),
141 else => asm volatile (
142 \\ svc #0
143 :
144 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
145 : "memory"
146 ),
147 }
148}
149
150pub fn restore_rt() callconv(.Naked) noreturn {
151 switch (@import("builtin").zig_backend) {
152 .stage2_c => asm volatile (
153 \\ mov r7, %[number]
154 \\ svc #0
155 :
156 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
157 : "memory"
158 ),
159 else => asm volatile (
160 \\ svc #0
161 :
162 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
163 : "memory"
164 ),
165 }
166}
167
168pub const MMAP2_UNIT = 4096;
169
170pub const F = struct {
171 pub const DUPFD = 0;
172 pub const GETFD = 1;
173 pub const SETFD = 2;
174 pub const GETFL = 3;
175 pub const SETFL = 4;
176
177 pub const SETOWN = 8;
178 pub const GETOWN = 9;
179 pub const SETSIG = 10;
180 pub const GETSIG = 11;
181
182 pub const GETLK = 12;
183 pub const SETLK = 13;
184 pub const SETLKW = 14;
185
186 pub const RDLCK = 0;
187 pub const WRLCK = 1;
188 pub const UNLCK = 2;
189
190 pub const SETOWN_EX = 15;
191 pub const GETOWN_EX = 16;
192
193 pub const GETOWNER_UIDS = 17;
194};
195
196pub const VDSO = struct {
197 pub const CGT_SYM = "__vdso_clock_gettime";
198 pub const CGT_VER = "LINUX_2.6";
199};
200
201pub const HWCAP = struct {
202 pub const SWP = 1 << 0;
203 pub const HALF = 1 << 1;
204 pub const THUMB = 1 << 2;
205 pub const @"26BIT" = 1 << 3;
206 pub const FAST_MULT = 1 << 4;
207 pub const FPA = 1 << 5;
208 pub const VFP = 1 << 6;
209 pub const EDSP = 1 << 7;
210 pub const JAVA = 1 << 8;
211 pub const IWMMXT = 1 << 9;
212 pub const CRUNCH = 1 << 10;
213 pub const THUMBEE = 1 << 11;
214 pub const NEON = 1 << 12;
215 pub const VFPv3 = 1 << 13;
216 pub const VFPv3D16 = 1 << 14;
217 pub const TLS = 1 << 15;
218 pub const VFPv4 = 1 << 16;
219 pub const IDIVA = 1 << 17;
220 pub const IDIVT = 1 << 18;
221 pub const VFPD32 = 1 << 19;
222 pub const IDIV = IDIVA | IDIVT;
223 pub const LPAE = 1 << 20;
224 pub const EVTSTRM = 1 << 21;
225};
226
227pub const Flock = extern struct {
228 type: i16,
229 whence: i16,
230 __pad0: [4]u8,
231 start: off_t,
232 len: off_t,
233 pid: pid_t,
234 __unused: [4]u8,
235};
236
237pub const msghdr = extern struct {
238 name: ?*sockaddr,
239 namelen: socklen_t,
240 iov: [*]iovec,
241 iovlen: i32,
242 control: ?*anyopaque,
243 controllen: socklen_t,
244 flags: i32,
245};
246
247pub const msghdr_const = extern struct {
248 name: ?*const sockaddr,
249 namelen: socklen_t,
250 iov: [*]const iovec_const,
251 iovlen: i32,
252 control: ?*const anyopaque,
253 controllen: socklen_t,
254 flags: i32,
255};
256
257pub const blksize_t = i32;
258pub const nlink_t = u32;
259pub const time_t = isize;
260pub const mode_t = u32;
261pub const off_t = i64;
262pub const ino_t = u64;
263pub const dev_t = u64;
264pub const blkcnt_t = i64;
265
266// The `stat` definition used by the Linux kernel.
267pub const Stat = extern struct {
268 dev: dev_t,
269 __dev_padding: u32,
270 __ino_truncated: u32,
271 mode: mode_t,
272 nlink: nlink_t,
273 uid: uid_t,
274 gid: gid_t,
275 rdev: dev_t,
276 __rdev_padding: u32,
277 size: off_t,
278 blksize: blksize_t,
279 blocks: blkcnt_t,
280 atim: timespec,
281 mtim: timespec,
282 ctim: timespec,
283 ino: ino_t,
284
285 pub fn atime(self: @This()) timespec {
286 return self.atim;
287 }
288
289 pub fn mtime(self: @This()) timespec {
290 return self.mtim;
291 }
292
293 pub fn ctime(self: @This()) timespec {
294 return self.ctim;
295 }
296};
297
298pub const timeval = extern struct {
299 sec: i32,
300 usec: i32,
301};
302
303pub const timezone = extern struct {
304 minuteswest: i32,
305 dsttime: i32,
306};
307
308pub const mcontext_t = extern struct {
309 trap_no: usize,
310 error_code: usize,
311 oldmask: usize,
312 arm_r0: usize,
313 arm_r1: usize,
314 arm_r2: usize,
315 arm_r3: usize,
316 arm_r4: usize,
317 arm_r5: usize,
318 arm_r6: usize,
319 arm_r7: usize,
320 arm_r8: usize,
321 arm_r9: usize,
322 arm_r10: usize,
323 arm_fp: usize,
324 arm_ip: usize,
325 arm_sp: usize,
326 arm_lr: usize,
327 arm_pc: usize,
328 arm_cpsr: usize,
329 fault_address: usize,
330};
331
332pub const ucontext_t = extern struct {
333 flags: usize,
334 link: ?*ucontext_t,
335 stack: stack_t,
336 mcontext: mcontext_t,
337 sigmask: sigset_t,
338 regspace: [64]u64,
339};
340
341/// TODO
342pub const getcontext = {};
343
344pub const Elf_Symndx = u32;
lib/std/os/linux/arm64.zig deleted-288
...@@ -1,288 +0,0 @@
1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
3const linux = std.os.linux;
4const SYS = linux.SYS;
5const socklen_t = linux.socklen_t;
6const sockaddr = linux.sockaddr;
7const iovec = std.posix.iovec;
8const iovec_const = std.posix.iovec_const;
9const uid_t = linux.uid_t;
10const gid_t = linux.gid_t;
11const pid_t = linux.pid_t;
12const stack_t = linux.stack_t;
13const sigset_t = linux.sigset_t;
14const timespec = std.os.linux.timespec;
15
16pub fn syscall0(number: SYS) usize {
17 return asm volatile ("svc #0"
18 : [ret] "={x0}" (-> usize),
19 : [number] "{x8}" (@intFromEnum(number)),
20 : "memory", "cc"
21 );
22}
23
24pub fn syscall1(number: SYS, arg1: usize) usize {
25 return asm volatile ("svc #0"
26 : [ret] "={x0}" (-> usize),
27 : [number] "{x8}" (@intFromEnum(number)),
28 [arg1] "{x0}" (arg1),
29 : "memory", "cc"
30 );
31}
32
33pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
34 return asm volatile ("svc #0"
35 : [ret] "={x0}" (-> usize),
36 : [number] "{x8}" (@intFromEnum(number)),
37 [arg1] "{x0}" (arg1),
38 [arg2] "{x1}" (arg2),
39 : "memory", "cc"
40 );
41}
42
43pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
44 return asm volatile ("svc #0"
45 : [ret] "={x0}" (-> usize),
46 : [number] "{x8}" (@intFromEnum(number)),
47 [arg1] "{x0}" (arg1),
48 [arg2] "{x1}" (arg2),
49 [arg3] "{x2}" (arg3),
50 : "memory", "cc"
51 );
52}
53
54pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
55 return asm volatile ("svc #0"
56 : [ret] "={x0}" (-> usize),
57 : [number] "{x8}" (@intFromEnum(number)),
58 [arg1] "{x0}" (arg1),
59 [arg2] "{x1}" (arg2),
60 [arg3] "{x2}" (arg3),
61 [arg4] "{x3}" (arg4),
62 : "memory", "cc"
63 );
64}
65
66pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
67 return asm volatile ("svc #0"
68 : [ret] "={x0}" (-> usize),
69 : [number] "{x8}" (@intFromEnum(number)),
70 [arg1] "{x0}" (arg1),
71 [arg2] "{x1}" (arg2),
72 [arg3] "{x2}" (arg3),
73 [arg4] "{x3}" (arg4),
74 [arg5] "{x4}" (arg5),
75 : "memory", "cc"
76 );
77}
78
79pub fn syscall6(
80 number: SYS,
81 arg1: usize,
82 arg2: usize,
83 arg3: usize,
84 arg4: usize,
85 arg5: usize,
86 arg6: usize,
87) usize {
88 return asm volatile ("svc #0"
89 : [ret] "={x0}" (-> usize),
90 : [number] "{x8}" (@intFromEnum(number)),
91 [arg1] "{x0}" (arg1),
92 [arg2] "{x1}" (arg2),
93 [arg3] "{x2}" (arg3),
94 [arg4] "{x3}" (arg4),
95 [arg5] "{x4}" (arg5),
96 [arg6] "{x5}" (arg6),
97 : "memory", "cc"
98 );
99}
100
101pub fn clone() callconv(.Naked) usize {
102 // __clone(func, stack, flags, arg, ptid, tls, ctid)
103 // x0, x1, w2, x3, x4, x5, x6
104 //
105 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
106 // x8, x0, x1, x2, x3, x4
107 asm volatile (
108 \\ // align stack and save func,arg
109 \\ and x1,x1,#-16
110 \\ stp x0,x3,[x1,#-16]!
111 \\
112 \\ // syscall
113 \\ uxtw x0,w2
114 \\ mov x2,x4
115 \\ mov x3,x5
116 \\ mov x4,x6
117 \\ mov x8,#220 // SYS_clone
118 \\ svc #0
119 \\
120 \\ cbz x0,1f
121 \\ // parent
122 \\ ret
123 \\ // child
124 \\1: ldp x1,x0,[sp],#16
125 \\ blr x1
126 \\ mov x8,#93 // SYS_exit
127 \\ svc #0
128 );
129}
130
131pub const restore = restore_rt;
132
133pub fn restore_rt() callconv(.Naked) noreturn {
134 switch (@import("builtin").zig_backend) {
135 .stage2_c => asm volatile (
136 \\ mov x8, %[number]
137 \\ svc #0
138 :
139 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cc"
141 ),
142 else => asm volatile (
143 \\ svc #0
144 :
145 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
146 : "memory", "cc"
147 ),
148 }
149}
150
151pub const F = struct {
152 pub const DUPFD = 0;
153 pub const GETFD = 1;
154 pub const SETFD = 2;
155 pub const GETFL = 3;
156 pub const SETFL = 4;
157
158 pub const SETOWN = 8;
159 pub const GETOWN = 9;
160 pub const SETSIG = 10;
161 pub const GETSIG = 11;
162
163 pub const GETLK = 5;
164 pub const SETLK = 6;
165 pub const SETLKW = 7;
166
167 pub const RDLCK = 0;
168 pub const WRLCK = 1;
169 pub const UNLCK = 2;
170
171 pub const SETOWN_EX = 15;
172 pub const GETOWN_EX = 16;
173
174 pub const GETOWNER_UIDS = 17;
175};
176
177pub const VDSO = struct {
178 pub const CGT_SYM = "__kernel_clock_gettime";
179 pub const CGT_VER = "LINUX_2.6.39";
180};
181
182pub const Flock = extern struct {
183 type: i16,
184 whence: i16,
185 start: off_t,
186 len: off_t,
187 pid: pid_t,
188 __unused: [4]u8,
189};
190
191pub const msghdr = extern struct {
192 name: ?*sockaddr,
193 namelen: socklen_t,
194 iov: [*]iovec,
195 iovlen: i32,
196 __pad1: i32 = 0,
197 control: ?*anyopaque,
198 controllen: socklen_t,
199 __pad2: socklen_t = 0,
200 flags: i32,
201};
202
203pub const msghdr_const = extern struct {
204 name: ?*const sockaddr,
205 namelen: socklen_t,
206 iov: [*]const iovec_const,
207 iovlen: i32,
208 __pad1: i32 = 0,
209 control: ?*const anyopaque,
210 controllen: socklen_t,
211 __pad2: socklen_t = 0,
212 flags: i32,
213};
214
215pub const blksize_t = i32;
216pub const nlink_t = u32;
217pub const time_t = isize;
218pub const mode_t = u32;
219pub const off_t = isize;
220pub const ino_t = usize;
221pub const dev_t = usize;
222pub const blkcnt_t = isize;
223
224// The `stat` definition used by the Linux kernel.
225pub const Stat = extern struct {
226 dev: dev_t,
227 ino: ino_t,
228 mode: mode_t,
229 nlink: nlink_t,
230 uid: uid_t,
231 gid: gid_t,
232 rdev: dev_t,
233 __pad: usize,
234 size: off_t,
235 blksize: blksize_t,
236 __pad2: i32,
237 blocks: blkcnt_t,
238 atim: timespec,
239 mtim: timespec,
240 ctim: timespec,
241 __unused: [2]u32,
242
243 pub fn atime(self: @This()) timespec {
244 return self.atim;
245 }
246
247 pub fn mtime(self: @This()) timespec {
248 return self.mtim;
249 }
250
251 pub fn ctime(self: @This()) timespec {
252 return self.ctim;
253 }
254};
255
256pub const timeval = extern struct {
257 sec: isize,
258 usec: isize,
259};
260
261pub const timezone = extern struct {
262 minuteswest: i32,
263 dsttime: i32,
264};
265
266pub const mcontext_t = extern struct {
267 fault_address: usize,
268 regs: [31]usize,
269 sp: usize,
270 pc: usize,
271 pstate: usize,
272 // Make sure the field is correctly aligned since this area
273 // holds various FP/vector registers
274 reserved1: [256 * 16]u8 align(16),
275};
276
277pub const ucontext_t = extern struct {
278 flags: usize,
279 link: ?*ucontext_t,
280 stack: stack_t,
281 sigmask: sigset_t,
282 mcontext: mcontext_t,
283};
284
285/// TODO
286pub const getcontext = {};
287
288pub const Elf_Symndx = u32;
lib/std/os/linux/pie.zig created+304
...@@ -0,0 +1,304 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const elf = std.elf;
4const assert = std.debug.assert;
5
6const R_AMD64_RELATIVE = 8;
7const R_386_RELATIVE = 8;
8const R_ARC_RELATIVE = 56;
9const R_ARM_RELATIVE = 23;
10const R_AARCH64_RELATIVE = 1027;
11const R_CSKY_RELATIVE = 9;
12const R_HEXAGON_RELATIVE = 35;
13const R_LARCH_RELATIVE = 3;
14const R_68K_RELATIVE = 22;
15const R_MIPS_RELATIVE = 128;
16const R_PPC_RELATIVE = 22;
17const R_RISCV_RELATIVE = 3;
18const R_390_RELATIVE = 12;
19const R_SPARC_RELATIVE = 22;
20
21const R_RELATIVE = switch (builtin.cpu.arch) {
22 .x86 => R_386_RELATIVE,
23 .x86_64 => R_AMD64_RELATIVE,
24 .arc => R_ARC_RELATIVE,
25 .arm, .armeb, .thumb, .thumbeb => R_ARM_RELATIVE,
26 .aarch64, .aarch64_be => R_AARCH64_RELATIVE,
27 .csky => R_CSKY_RELATIVE,
28 .hexagon => R_HEXAGON_RELATIVE,
29 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,
30 .m68k => R_68K_RELATIVE,
31 .mips, .mipsel, .mips64, .mips64el => R_MIPS_RELATIVE,
32 .powerpc, .powerpcle, .powerpc64, .powerpc64le => R_PPC_RELATIVE,
33 .riscv32, .riscv64 => R_RISCV_RELATIVE,
34 .s390x => R_390_RELATIVE,
35 .sparc, .sparc64 => R_SPARC_RELATIVE,
36 else => @compileError("Missing R_RELATIVE definition for this target"),
37};
38
39// Obtain a pointer to the _DYNAMIC array.
40// We have to compute its address as a PC-relative quantity not to require a
41// relocation that, at this point, is not yet applied.
42inline fn getDynamicSymbol() [*]elf.Dyn {
43 return switch (builtin.cpu.arch) {
44 .x86 => asm volatile (
45 \\ .weak _DYNAMIC
46 \\ .hidden _DYNAMIC
47 \\ call 1f
48 \\ 1: pop %[ret]
49 \\ lea _DYNAMIC-1b(%[ret]), %[ret]
50 : [ret] "=r" (-> [*]elf.Dyn),
51 ),
52 .x86_64 => asm volatile (
53 \\ .weak _DYNAMIC
54 \\ .hidden _DYNAMIC
55 \\ lea _DYNAMIC(%%rip), %[ret]
56 : [ret] "=r" (-> [*]elf.Dyn),
57 ),
58 .arc => asm volatile (
59 \\ .weak _DYNAMIC
60 \\ .hidden _DYNAMIC
61 \\ add %[ret], pcl, _DYNAMIC@pcl
62 : [ret] "=r" (-> [*]elf.Dyn),
63 ),
64 // Work around the limited offset range of `ldr`
65 .arm, .armeb, .thumb, .thumbeb => asm volatile (
66 \\ .weak _DYNAMIC
67 \\ .hidden _DYNAMIC
68 \\ ldr %[ret], 1f
69 \\ add %[ret], pc
70 \\ b 2f
71 \\ 1: .word _DYNAMIC-1b
72 \\ 2:
73 : [ret] "=r" (-> [*]elf.Dyn),
74 ),
75 // A simple `adr` is not enough as it has a limited offset range
76 .aarch64, .aarch64_be => asm volatile (
77 \\ .weak _DYNAMIC
78 \\ .hidden _DYNAMIC
79 \\ adrp %[ret], _DYNAMIC
80 \\ add %[ret], %[ret], #:lo12:_DYNAMIC
81 : [ret] "=r" (-> [*]elf.Dyn),
82 ),
83 // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first
84 // entry in the GOT is defined to hold the address of _DYNAMIC.
85 .csky => asm volatile (
86 \\ mov %[ret], gb
87 \\ ldw %[ret], %[ret]
88 : [ret] "=r" (-> [*]elf.Dyn),
89 ),
90 .hexagon => asm volatile (
91 \\ .weak _DYNAMIC
92 \\ .hidden _DYNAMIC
93 \\ jump 1f
94 \\ .word _DYNAMIC - .
95 \\ 1:
96 \\ r1 = pc
97 \\ r1 = add(r1, #-4)
98 \\ %[ret] = memw(r1)
99 \\ %[ret] = add(r1, %[ret])
100 : [ret] "=r" (-> [*]elf.Dyn),
101 :
102 : "r1"
103 ),
104 .loongarch32, .loongarch64 => asm volatile (
105 \\ .weak _DYNAMIC
106 \\ .hidden _DYNAMIC
107 \\ la.local %[ret], _DYNAMIC
108 : [ret] "=r" (-> [*]elf.Dyn),
109 ),
110 // Note that the - 8 is needed because pc in the second lea instruction points into the
111 // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.)
112 .m68k => asm volatile (
113 \\ .weak _DYNAMIC
114 \\ .hidden _DYNAMIC
115 \\ lea _DYNAMIC - . - 8, %[ret]
116 \\ lea (%[ret], %%pc), %[ret]
117 : [ret] "=r" (-> [*]elf.Dyn),
118 ),
119 .mips, .mipsel => asm volatile (
120 \\ .weak _DYNAMIC
121 \\ .hidden _DYNAMIC
122 \\ bal 1f
123 \\ .gpword _DYNAMIC
124 \\ 1:
125 \\ lw %[ret], 0($ra)
126 \\ addu %[ret], %[ret], $gp
127 : [ret] "=r" (-> [*]elf.Dyn),
128 :
129 : "lr"
130 ),
131 .mips64, .mips64el => asm volatile (
132 \\ .weak _DYNAMIC
133 \\ .hidden _DYNAMIC
134 \\ .balign 8
135 \\ bal 1f
136 \\ .gpdword _DYNAMIC
137 \\ 1:
138 \\ ld %[ret], 0($ra)
139 \\ daddu %[ret], %[ret], $gp
140 : [ret] "=r" (-> [*]elf.Dyn),
141 :
142 : "lr"
143 ),
144 .powerpc, .powerpcle => asm volatile (
145 \\ .weak _DYNAMIC
146 \\ .hidden _DYNAMIC
147 \\ bl 1f
148 \\ .long _DYNAMIC - .
149 \\ 1:
150 \\ mflr %[ret]
151 \\ lwz 4, 0(%[ret])
152 \\ add %[ret], 4, %[ret]
153 : [ret] "=r" (-> [*]elf.Dyn),
154 :
155 : "lr", "r4"
156 ),
157 .powerpc64, .powerpc64le => asm volatile (
158 \\ .weak _DYNAMIC
159 \\ .hidden _DYNAMIC
160 \\ bl 1f
161 \\ .quad _DYNAMIC - .
162 \\ 1:
163 \\ mflr %[ret]
164 \\ ld 4, 0(%[ret])
165 \\ add %[ret], 4, %[ret]
166 : [ret] "=r" (-> [*]elf.Dyn),
167 :
168 : "lr", "r4"
169 ),
170 .riscv32, .riscv64 => asm volatile (
171 \\ .weak _DYNAMIC
172 \\ .hidden _DYNAMIC
173 \\ lla %[ret], _DYNAMIC
174 : [ret] "=r" (-> [*]elf.Dyn),
175 ),
176 .s390x => asm volatile (
177 \\ .weak _DYNAMIC
178 \\ .hidden _DYNAMIC
179 \\ larl %[ret], 1f
180 \\ ag %[ret], 0(%[ret])
181 \\ b 2f
182 \\ 1: .quad _DYNAMIC - .
183 \\ 2:
184 : [ret] "=r" (-> [*]elf.Dyn),
185 ),
186 // The compiler does not necessarily have any obligation to load the `l7` register (pointing
187 // to the GOT), so do it ourselves just in case.
188 .sparc, .sparc64 => asm volatile (
189 \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7
190 \\ call 1f
191 \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7
192 \\ 1:
193 \\ add %%l7, %%o7, %[ret]
194 : [ret] "=r" (-> [*]elf.Dyn),
195 ),
196 else => {
197 @compileError("PIE startup is not yet supported for this target!");
198 },
199 };
200}
201
202pub fn relocate(phdrs: []elf.Phdr) void {
203 @setRuntimeSafety(false);
204 @disableInstrumentation();
205
206 const dynv = getDynamicSymbol();
207
208 // Recover the delta applied by the loader by comparing the effective and
209 // the theoretical load addresses for the `_DYNAMIC` symbol.
210 const base_addr = base: {
211 for (phdrs) |*phdr| {
212 if (phdr.p_type != elf.PT_DYNAMIC) continue;
213 break :base @intFromPtr(dynv) - phdr.p_vaddr;
214 }
215 // This is not supposed to happen for well-formed binaries.
216 @trap();
217 };
218
219 var sorted_dynv: [elf.DT_NUM]elf.Addr = undefined;
220
221 // Zero-initialized this way to prevent the compiler from turning this into
222 // `memcpy` or `memset` calls (which can require relocations).
223 for (&sorted_dynv) |*dyn| {
224 const pdyn: *volatile elf.Addr = @ptrCast(dyn);
225 pdyn.* = 0;
226 }
227
228 {
229 // `dynv` has no defined order. Fix that.
230 var i: usize = 0;
231 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {
232 if (dynv[i].d_tag < elf.DT_NUM) sorted_dynv[@bitCast(dynv[i].d_tag)] = dynv[i].d_val;
233 }
234 }
235
236 // Deal with the GOT relocations that MIPS uses first.
237 if (builtin.cpu.arch.isMIPS()) {
238 const count: elf.Addr = blk: {
239 // This is an architecture-specific tag, so not part of `sorted_dynv`.
240 var i: usize = 0;
241 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {
242 if (dynv[i].d_tag == elf.DT_MIPS_LOCAL_GOTNO) break :blk dynv[i].d_val;
243 }
244
245 break :blk 0;
246 };
247
248 const got: [*]usize = @ptrFromInt(base_addr + sorted_dynv[elf.DT_PLTGOT]);
249
250 for (0..count) |i| {
251 got[i] += base_addr;
252 }
253 }
254
255 // Apply normal relocations.
256
257 const rel = sorted_dynv[elf.DT_REL];
258 if (rel != 0) {
259 const rels = @call(.always_inline, std.mem.bytesAsSlice, .{
260 elf.Rel,
261 @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]],
262 });
263 for (rels) |r| {
264 if (r.r_type() != R_RELATIVE) continue;
265 @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr;
266 }
267 }
268
269 const rela = sorted_dynv[elf.DT_RELA];
270 if (rela != 0) {
271 const relas = @call(.always_inline, std.mem.bytesAsSlice, .{
272 elf.Rela,
273 @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]],
274 });
275 for (relas) |r| {
276 if (r.r_type() != R_RELATIVE) continue;
277 @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend));
278 }
279 }
280
281 const relr = sorted_dynv[elf.DT_RELR];
282 if (relr != 0) {
283 const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{
284 elf.Relr,
285 @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]],
286 });
287 var current: [*]usize = undefined;
288 for (relrs) |r| {
289 if ((r & 1) == 0) {
290 current = @ptrFromInt(base_addr + r);
291 current[0] += base_addr;
292 current += 1;
293 } else {
294 // Skip the first bit; there are 63 locations in the bitmap.
295 var i: if (@sizeOf(usize) == 8) u6 else u5 = 1;
296 while (i < @bitSizeOf(elf.Relr)) : (i += 1) {
297 if (((r >> i) & 1) != 0) current[i] += base_addr;
298 }
299
300 current += @bitSizeOf(elf.Relr) - 1;
301 }
302 }
303 }
304}
lib/std/os/linux/start_pie.zig deleted-304
...@@ -1,304 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const elf = std.elf;
4const assert = std.debug.assert;
5
6const R_AMD64_RELATIVE = 8;
7const R_386_RELATIVE = 8;
8const R_ARC_RELATIVE = 56;
9const R_ARM_RELATIVE = 23;
10const R_AARCH64_RELATIVE = 1027;
11const R_CSKY_RELATIVE = 9;
12const R_HEXAGON_RELATIVE = 35;
13const R_LARCH_RELATIVE = 3;
14const R_68K_RELATIVE = 22;
15const R_MIPS_RELATIVE = 128;
16const R_PPC_RELATIVE = 22;
17const R_RISCV_RELATIVE = 3;
18const R_390_RELATIVE = 12;
19const R_SPARC_RELATIVE = 22;
20
21const R_RELATIVE = switch (builtin.cpu.arch) {
22 .x86 => R_386_RELATIVE,
23 .x86_64 => R_AMD64_RELATIVE,
24 .arc => R_ARC_RELATIVE,
25 .arm, .armeb, .thumb, .thumbeb => R_ARM_RELATIVE,
26 .aarch64, .aarch64_be => R_AARCH64_RELATIVE,
27 .csky => R_CSKY_RELATIVE,
28 .hexagon => R_HEXAGON_RELATIVE,
29 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,
30 .m68k => R_68K_RELATIVE,
31 .mips, .mipsel, .mips64, .mips64el => R_MIPS_RELATIVE,
32 .powerpc, .powerpcle, .powerpc64, .powerpc64le => R_PPC_RELATIVE,
33 .riscv32, .riscv64 => R_RISCV_RELATIVE,
34 .s390x => R_390_RELATIVE,
35 .sparc, .sparc64 => R_SPARC_RELATIVE,
36 else => @compileError("Missing R_RELATIVE definition for this target"),
37};
38
39// Obtain a pointer to the _DYNAMIC array.
40// We have to compute its address as a PC-relative quantity not to require a
41// relocation that, at this point, is not yet applied.
42inline fn getDynamicSymbol() [*]elf.Dyn {
43 return switch (builtin.cpu.arch) {
44 .x86 => asm volatile (
45 \\ .weak _DYNAMIC
46 \\ .hidden _DYNAMIC
47 \\ call 1f
48 \\ 1: pop %[ret]
49 \\ lea _DYNAMIC-1b(%[ret]), %[ret]
50 : [ret] "=r" (-> [*]elf.Dyn),
51 ),
52 .x86_64 => asm volatile (
53 \\ .weak _DYNAMIC
54 \\ .hidden _DYNAMIC
55 \\ lea _DYNAMIC(%%rip), %[ret]
56 : [ret] "=r" (-> [*]elf.Dyn),
57 ),
58 .arc => asm volatile (
59 \\ .weak _DYNAMIC
60 \\ .hidden _DYNAMIC
61 \\ add %[ret], pcl, _DYNAMIC@pcl
62 : [ret] "=r" (-> [*]elf.Dyn),
63 ),
64 // Work around the limited offset range of `ldr`
65 .arm, .armeb, .thumb, .thumbeb => asm volatile (
66 \\ .weak _DYNAMIC
67 \\ .hidden _DYNAMIC
68 \\ ldr %[ret], 1f
69 \\ add %[ret], pc
70 \\ b 2f
71 \\ 1: .word _DYNAMIC-1b
72 \\ 2:
73 : [ret] "=r" (-> [*]elf.Dyn),
74 ),
75 // A simple `adr` is not enough as it has a limited offset range
76 .aarch64, .aarch64_be => asm volatile (
77 \\ .weak _DYNAMIC
78 \\ .hidden _DYNAMIC
79 \\ adrp %[ret], _DYNAMIC
80 \\ add %[ret], %[ret], #:lo12:_DYNAMIC
81 : [ret] "=r" (-> [*]elf.Dyn),
82 ),
83 // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first
84 // entry in the GOT is defined to hold the address of _DYNAMIC.
85 .csky => asm volatile (
86 \\ mov %[ret], gb
87 \\ ldw %[ret], %[ret]
88 : [ret] "=r" (-> [*]elf.Dyn),
89 ),
90 .hexagon => asm volatile (
91 \\ .weak _DYNAMIC
92 \\ .hidden _DYNAMIC
93 \\ jump 1f
94 \\ .word _DYNAMIC - .
95 \\ 1:
96 \\ r1 = pc
97 \\ r1 = add(r1, #-4)
98 \\ %[ret] = memw(r1)
99 \\ %[ret] = add(r1, %[ret])
100 : [ret] "=r" (-> [*]elf.Dyn),
101 :
102 : "r1"
103 ),
104 .loongarch32, .loongarch64 => asm volatile (
105 \\ .weak _DYNAMIC
106 \\ .hidden _DYNAMIC
107 \\ la.local %[ret], _DYNAMIC
108 : [ret] "=r" (-> [*]elf.Dyn),
109 ),
110 // Note that the - 8 is needed because pc in the second lea instruction points into the
111 // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.)
112 .m68k => asm volatile (
113 \\ .weak _DYNAMIC
114 \\ .hidden _DYNAMIC
115 \\ lea _DYNAMIC - . - 8, %[ret]
116 \\ lea (%[ret], %%pc), %[ret]
117 : [ret] "=r" (-> [*]elf.Dyn),
118 ),
119 .mips, .mipsel => asm volatile (
120 \\ .weak _DYNAMIC
121 \\ .hidden _DYNAMIC
122 \\ bal 1f
123 \\ .gpword _DYNAMIC
124 \\ 1:
125 \\ lw %[ret], 0($ra)
126 \\ addu %[ret], %[ret], $gp
127 : [ret] "=r" (-> [*]elf.Dyn),
128 :
129 : "lr"
130 ),
131 .mips64, .mips64el => asm volatile (
132 \\ .weak _DYNAMIC
133 \\ .hidden _DYNAMIC
134 \\ .balign 8
135 \\ bal 1f
136 \\ .gpdword _DYNAMIC
137 \\ 1:
138 \\ ld %[ret], 0($ra)
139 \\ daddu %[ret], %[ret], $gp
140 : [ret] "=r" (-> [*]elf.Dyn),
141 :
142 : "lr"
143 ),
144 .powerpc, .powerpcle => asm volatile (
145 \\ .weak _DYNAMIC
146 \\ .hidden _DYNAMIC
147 \\ bl 1f
148 \\ .long _DYNAMIC - .
149 \\ 1:
150 \\ mflr %[ret]
151 \\ lwz 4, 0(%[ret])
152 \\ add %[ret], 4, %[ret]
153 : [ret] "=r" (-> [*]elf.Dyn),
154 :
155 : "lr", "r4"
156 ),
157 .powerpc64, .powerpc64le => asm volatile (
158 \\ .weak _DYNAMIC
159 \\ .hidden _DYNAMIC
160 \\ bl 1f
161 \\ .quad _DYNAMIC - .
162 \\ 1:
163 \\ mflr %[ret]
164 \\ ld 4, 0(%[ret])
165 \\ add %[ret], 4, %[ret]
166 : [ret] "=r" (-> [*]elf.Dyn),
167 :
168 : "lr", "r4"
169 ),
170 .riscv32, .riscv64 => asm volatile (
171 \\ .weak _DYNAMIC
172 \\ .hidden _DYNAMIC
173 \\ lla %[ret], _DYNAMIC
174 : [ret] "=r" (-> [*]elf.Dyn),
175 ),
176 .s390x => asm volatile (
177 \\ .weak _DYNAMIC
178 \\ .hidden _DYNAMIC
179 \\ larl %[ret], 1f
180 \\ ag %[ret], 0(%[ret])
181 \\ b 2f
182 \\ 1: .quad _DYNAMIC - .
183 \\ 2:
184 : [ret] "=r" (-> [*]elf.Dyn),
185 ),
186 // The compiler does not necessarily have any obligation to load the `l7` register (pointing
187 // to the GOT), so do it ourselves just in case.
188 .sparc, .sparc64 => asm volatile (
189 \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7
190 \\ call 1f
191 \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7
192 \\ 1:
193 \\ add %%l7, %%o7, %[ret]
194 : [ret] "=r" (-> [*]elf.Dyn),
195 ),
196 else => {
197 @compileError("PIE startup is not yet supported for this target!");
198 },
199 };
200}
201
202pub fn relocate(phdrs: []elf.Phdr) void {
203 @setRuntimeSafety(false);
204 @disableInstrumentation();
205
206 const dynv = getDynamicSymbol();
207
208 // Recover the delta applied by the loader by comparing the effective and
209 // the theoretical load addresses for the `_DYNAMIC` symbol.
210 const base_addr = base: {
211 for (phdrs) |*phdr| {
212 if (phdr.p_type != elf.PT_DYNAMIC) continue;
213 break :base @intFromPtr(dynv) - phdr.p_vaddr;
214 }
215 // This is not supposed to happen for well-formed binaries.
216 @trap();
217 };
218
219 var sorted_dynv: [elf.DT_NUM]elf.Addr = undefined;
220
221 // Zero-initialized this way to prevent the compiler from turning this into
222 // `memcpy` or `memset` calls (which can require relocations).
223 for (&sorted_dynv) |*dyn| {
224 const pdyn: *volatile elf.Addr = @ptrCast(dyn);
225 pdyn.* = 0;
226 }
227
228 {
229 // `dynv` has no defined order. Fix that.
230 var i: usize = 0;
231 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {
232 if (dynv[i].d_tag < elf.DT_NUM) sorted_dynv[@bitCast(dynv[i].d_tag)] = dynv[i].d_val;
233 }
234 }
235
236 // Deal with the GOT relocations that MIPS uses first.
237 if (builtin.cpu.arch.isMIPS()) {
238 const count: elf.Addr = blk: {
239 // This is an architecture-specific tag, so not part of `sorted_dynv`.
240 var i: usize = 0;
241 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {
242 if (dynv[i].d_tag == elf.DT_MIPS_LOCAL_GOTNO) break :blk dynv[i].d_val;
243 }
244
245 break :blk 0;
246 };
247
248 const got: [*]usize = @ptrFromInt(base_addr + sorted_dynv[elf.DT_PLTGOT]);
249
250 for (0..count) |i| {
251 got[i] += base_addr;
252 }
253 }
254
255 // Apply normal relocations.
256
257 const rel = sorted_dynv[elf.DT_REL];
258 if (rel != 0) {
259 const rels = @call(.always_inline, std.mem.bytesAsSlice, .{
260 elf.Rel,
261 @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]],
262 });
263 for (rels) |r| {
264 if (r.r_type() != R_RELATIVE) continue;
265 @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr;
266 }
267 }
268
269 const rela = sorted_dynv[elf.DT_RELA];
270 if (rela != 0) {
271 const relas = @call(.always_inline, std.mem.bytesAsSlice, .{
272 elf.Rela,
273 @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]],
274 });
275 for (relas) |r| {
276 if (r.r_type() != R_RELATIVE) continue;
277 @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend));
278 }
279 }
280
281 const relr = sorted_dynv[elf.DT_RELR];
282 if (relr != 0) {
283 const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{
284 elf.Relr,
285 @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]],
286 });
287 var current: [*]usize = undefined;
288 for (relrs) |r| {
289 if ((r & 1) == 0) {
290 current = @ptrFromInt(base_addr + r);
291 current[0] += base_addr;
292 current += 1;
293 } else {
294 // Skip the first bit; there are 63 locations in the bitmap.
295 var i: if (@sizeOf(usize) == 8) u6 else u5 = 1;
296 while (i < @bitSizeOf(elf.Relr)) : (i += 1) {
297 if (((r >> i) & 1) != 0) current[i] += base_addr;
298 }
299
300 current += @bitSizeOf(elf.Relr) - 1;
301 }
302 }
303 }
304}
lib/std/os/linux/thumb.zig+1-1
...@@ -141,7 +141,7 @@ pub fn syscall6(...@@ -141,7 +141,7 @@ pub fn syscall6(
141 );141 );
142}142}
143143
144pub const clone = @import("arm-eabi.zig").clone;144pub const clone = @import("arm.zig").clone;
145145
146pub fn restore() callconv(.Naked) noreturn {146pub fn restore() callconv(.Naked) noreturn {
147 asm volatile (147 asm volatile (