authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-06 13:35:56+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-06 13:35:56+02:00
logbe5378b03805fa95b3cf36b6727d2c364c155e64
treee6571591425e1cf8e373a9663010de536b644148
parent008bb1f1201a4b4987bf00de9daf46185aa9292d
parent45644b7e152e851b9f9f51095e3ce1ca7fcc8a56
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21587 from alexrp/hexagon-porting

Some initial `hexagon-linux` port work

15 files changed, 1217 insertions(+), 947 deletions(-)

lib/std/atomic.zig+4-2
...@@ -433,18 +433,20 @@ pub const cache_line = switch (builtin.cpu.arch) {...@@ -433,18 +433,20 @@ pub const cache_line = switch (builtin.cpu.arch) {
433 .powerpc64le,433 .powerpc64le,
434 => 128,434 => 128,
435435
436 // https://github.com/llvm/llvm-project/blob/e379094328e49731a606304f7e3559d4f1fa96f9/clang/lib/Basic/Targets/Hexagon.h#L145-L151
437 .hexagon,
438 => if (std.Target.hexagon.featureSetHas(builtin.target.cpu.features, .v73)) 64 else 32,
439
436 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7440 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
437 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7441 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
438 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7442 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
439 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9443 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
440 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7444 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
441 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/hexagon/include/asm/cache.h#L13
442 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14445 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14
443 .arm,446 .arm,
444 .armeb,447 .armeb,
445 .thumb,448 .thumb,
446 .thumbeb,449 .thumbeb,
447 .hexagon,
448 .mips,450 .mips,
449 .mipsel,451 .mipsel,
450 .mips64,452 .mips64,
lib/std/os/linux.zig+6-5
...@@ -37,8 +37,9 @@ const syscall_bits = switch (native_arch) {...@@ -37,8 +37,9 @@ 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 .hexagon => @import("linux/hexagon.zig"),
42 .riscv32 => @import("linux/riscv32.zig"),43 .riscv32 => @import("linux/riscv32.zig"),
43 .riscv64 => @import("linux/riscv64.zig"),44 .riscv64 => @import("linux/riscv64.zig"),
44 .sparc64 => @import("linux/sparc64.zig"),45 .sparc64 => @import("linux/sparc64.zig"),
...@@ -116,7 +117,7 @@ pub const user_desc = arch_bits.user_desc;...@@ -116,7 +117,7 @@ pub const user_desc = arch_bits.user_desc;
116pub const getcontext = arch_bits.getcontext;117pub const getcontext = arch_bits.getcontext;
117118
118pub const tls = @import("linux/tls.zig");119pub const tls = @import("linux/tls.zig");
119pub const pie = @import("linux/start_pie.zig");120pub const pie = @import("linux/pie.zig");
120pub const BPF = @import("linux/bpf.zig");121pub const BPF = @import("linux/bpf.zig");
121pub const IOCTL = @import("linux/ioctl.zig");122pub const IOCTL = @import("linux/ioctl.zig");
122pub const SECCOMP = @import("linux/seccomp.zig");123pub const SECCOMP = @import("linux/seccomp.zig");
...@@ -277,7 +278,7 @@ pub const MAP = switch (native_arch) {...@@ -277,7 +278,7 @@ pub const MAP = switch (native_arch) {
277 UNINITIALIZED: bool = false,278 UNINITIALIZED: bool = false,
278 _: u5 = 0,279 _: u5 = 0,
279 },280 },
280 .s390x => packed struct(u32) {281 .hexagon, .s390x => packed struct(u32) {
281 TYPE: MAP_TYPE,282 TYPE: MAP_TYPE,
282 FIXED: bool = false,283 FIXED: bool = false,
283 ANONYMOUS: bool = false,284 ANONYMOUS: bool = false,
...@@ -441,7 +442,7 @@ pub const O = switch (native_arch) {...@@ -441,7 +442,7 @@ pub const O = switch (native_arch) {
441 TMPFILE: bool = false,442 TMPFILE: bool = false,
442 _: u9 = 0,443 _: u9 = 0,
443 },444 },
444 .s390x => packed struct(u32) {445 .hexagon, .s390x => packed struct(u32) {
445 ACCMODE: ACCMODE = .RDONLY,446 ACCMODE: ACCMODE = .RDONLY,
446 _2: u4 = 0,447 _2: u4 = 0,
447 CREAT: bool = false,448 CREAT: bool = false,
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/hexagon.zig created+254
...@@ -0,0 +1,254 @@
1const std = @import("../../std.zig");
2const iovec = std.posix.iovec;
3const iovec_const = std.posix.iovec_const;
4const linux = std.os.linux;
5const SYS = linux.SYS;
6const uid_t = std.os.linux.uid_t;
7const gid_t = std.os.linux.gid_t;
8const pid_t = std.os.linux.pid_t;
9const sockaddr = linux.sockaddr;
10const socklen_t = linux.socklen_t;
11const timespec = std.os.linux.timespec;
12
13pub fn syscall0(number: SYS) usize {
14 return asm volatile ("trap0(#1)"
15 : [ret] "={r0}" (-> usize),
16 : [number] "{r6}" (@intFromEnum(number)),
17 : "memory"
18 );
19}
20
21pub fn syscall1(number: SYS, arg1: usize) usize {
22 return asm volatile ("trap0(#1)"
23 : [ret] "={r0}" (-> usize),
24 : [number] "{r6}" (@intFromEnum(number)),
25 [arg1] "{r0}" (arg1),
26 : "memory"
27 );
28}
29
30pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
31 return asm volatile ("trap0(#1)"
32 : [ret] "={r0}" (-> usize),
33 : [number] "{r6}" (@intFromEnum(number)),
34 [arg1] "{r0}" (arg1),
35 [arg2] "{r1}" (arg2),
36 : "memory"
37 );
38}
39
40pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
41 return asm volatile ("trap0(#1)"
42 : [ret] "={r0}" (-> usize),
43 : [number] "{r6}" (@intFromEnum(number)),
44 [arg1] "{r0}" (arg1),
45 [arg2] "{r1}" (arg2),
46 [arg3] "{r2}" (arg3),
47 : "memory"
48 );
49}
50
51pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
52 return asm volatile ("trap0(#1)"
53 : [ret] "={r0}" (-> usize),
54 : [number] "{r6}" (@intFromEnum(number)),
55 [arg1] "{r0}" (arg1),
56 [arg2] "{r1}" (arg2),
57 [arg3] "{r2}" (arg3),
58 [arg4] "{r3}" (arg4),
59 : "memory"
60 );
61}
62
63pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
64 return asm volatile ("trap0(#1)"
65 : [ret] "={r0}" (-> usize),
66 : [number] "{r6}" (@intFromEnum(number)),
67 [arg1] "{r0}" (arg1),
68 [arg2] "{r1}" (arg2),
69 [arg3] "{r2}" (arg3),
70 [arg4] "{r3}" (arg4),
71 [arg5] "{r4}" (arg5),
72 : "memory"
73 );
74}
75
76pub fn syscall6(
77 number: SYS,
78 arg1: usize,
79 arg2: usize,
80 arg3: usize,
81 arg4: usize,
82 arg5: usize,
83 arg6: usize,
84) usize {
85 return asm volatile ("trap0(#1)"
86 : [ret] "={r0}" (-> usize),
87 : [number] "{r6}" (@intFromEnum(number)),
88 [arg1] "{r0}" (arg1),
89 [arg2] "{r1}" (arg2),
90 [arg3] "{r2}" (arg3),
91 [arg4] "{r3}" (arg4),
92 [arg5] "{r4}" (arg5),
93 [arg6] "{r5}" (arg6),
94 : "memory"
95 );
96}
97
98pub fn clone() callconv(.Naked) usize {
99 // __clone(func, stack, flags, arg, ptid, tls, ctid)
100 // r0, r1, r2, r3, r4, r5, +0
101 //
102 // syscall(SYS_clone, flags, stack, ptid, ctid, tls)
103 // r6 r0, r1, r2, r3, r4
104 asm volatile (
105 \\ allocframe(#8)
106 \\
107 \\ r11 = r0
108 \\ r10 = r3
109 \\
110 \\ r6 = #220 // SYS_clone
111 \\ r0 = r2
112 \\ r1 = and(r1, #-8)
113 \\ r2 = r4
114 \\ r3 = memw(r30 + #8)
115 \\ r4 = r5
116 \\ trap0(#1)
117 \\
118 \\ p0 = cmp.eq(r0, #0)
119 \\ if (!p0) dealloc_return
120 \\
121 \\ r0 = r10
122 \\ callr r11
123 \\
124 \\ r6 = #93 // SYS_exit
125 \\ r0 = #0
126 \\ trap0(#1)
127 );
128}
129
130pub const restore = restore_rt;
131
132pub fn restore_rt() callconv(.Naked) noreturn {
133 asm volatile (
134 \\ trap0(#0)
135 :
136 : [number] "{r6}" (@intFromEnum(SYS.rt_sigreturn)),
137 : "memory"
138 );
139}
140
141pub const F = struct {
142 pub const DUPFD = 0;
143 pub const GETFD = 1;
144 pub const SETFD = 2;
145 pub const GETFL = 3;
146 pub const SETFL = 4;
147 pub const GETLK = 5;
148 pub const SETLK = 6;
149 pub const SETLKW = 7;
150 pub const SETOWN = 8;
151 pub const GETOWN = 9;
152 pub const SETSIG = 10;
153 pub const GETSIG = 11;
154
155 pub const RDLCK = 0;
156 pub const WRLCK = 1;
157 pub const UNLCK = 2;
158
159 pub const SETOWN_EX = 15;
160 pub const GETOWN_EX = 16;
161
162 pub const GETOWNER_UIDS = 17;
163};
164
165pub const timeval = extern struct {
166 sec: time_t,
167 usec: i32,
168};
169
170pub const Flock = extern struct {
171 type: i16,
172 whence: i16,
173 start: off_t,
174 len: off_t,
175 pid: pid_t,
176 __unused: [4]u8,
177};
178
179pub const msghdr = extern struct {
180 name: ?*sockaddr,
181 namelen: socklen_t,
182 iov: [*]iovec,
183 iovlen: i32,
184 __pad1: i32 = 0,
185 control: ?*anyopaque,
186 controllen: socklen_t,
187 __pad2: socklen_t = 0,
188 flags: i32,
189};
190
191pub const msghdr_const = extern struct {
192 name: ?*const sockaddr,
193 namelen: socklen_t,
194 iov: [*]const iovec_const,
195 iovlen: i32,
196 __pad1: i32 = 0,
197 control: ?*const anyopaque,
198 controllen: socklen_t,
199 __pad2: socklen_t = 0,
200 flags: i32,
201};
202
203pub const blksize_t = i32;
204pub const nlink_t = u32;
205pub const time_t = i32;
206pub const mode_t = u32;
207pub const off_t = i64;
208pub const ino_t = u64;
209pub const dev_t = u64;
210pub const blkcnt_t = i64;
211
212// The `stat` definition used by the Linux kernel.
213pub const Stat = extern struct {
214 dev: dev_t,
215 ino: ino_t,
216 mode: mode_t,
217 nlink: nlink_t,
218 uid: uid_t,
219 gid: gid_t,
220 rdev: dev_t,
221 __pad: u32,
222 size: off_t,
223 blksize: blksize_t,
224 __pad2: i32,
225 blocks: blkcnt_t,
226 atim: timespec,
227 mtim: timespec,
228 ctim: timespec,
229 __unused: [2]u32,
230
231 pub fn atime(self: @This()) timespec {
232 return self.atim;
233 }
234
235 pub fn mtime(self: @This()) timespec {
236 return self.mtim;
237 }
238
239 pub fn ctime(self: @This()) timespec {
240 return self.ctim;
241 }
242};
243
244pub const Elf_Symndx = u32;
245
246pub const MMAP2_UNIT = 4096;
247
248pub const VDSO = void;
249
250/// TODO
251pub const ucontext_t = void;
252
253/// TODO
254pub const getcontext = {};
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/syscalls.zig+2-2
...@@ -6852,7 +6852,7 @@ pub const Arc = enum(usize) {...@@ -6852,7 +6852,7 @@ pub const Arc = enum(usize) {
6852 keyctl = 219,6852 keyctl = 219,
6853 clone = 220,6853 clone = 220,
6854 execve = 221,6854 execve = 221,
6855 mmap_pgoff = 222,6855 mmap2 = 222,
6856 fadvise64_64 = 223,6856 fadvise64_64 = 223,
6857 swapon = 224,6857 swapon = 224,
6858 swapoff = 225,6858 swapoff = 225,
...@@ -7538,7 +7538,7 @@ pub const Hexagon = enum(usize) {...@@ -7538,7 +7538,7 @@ pub const Hexagon = enum(usize) {
7538 keyctl = 219,7538 keyctl = 219,
7539 clone = 220,7539 clone = 220,
7540 execve = 221,7540 execve = 221,
7541 mmap_pgoff = 222,7541 mmap2 = 222,
7542 fadvise64_64 = 223,7542 fadvise64_64 = 223,
7543 swapon = 224,7543 swapon = 224,
7544 swapoff = 225,7544 swapoff = 225,
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 (
lib/std/zig/system.zig+10
...@@ -386,6 +386,16 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -386,6 +386,16 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
386 query.cpu_features_sub,386 query.cpu_features_sub,
387 );387 );
388388
389 if (cpu_arch == .hexagon) {
390 // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature
391 // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize`
392 // command line parameter for the Hexagon backend to 0, so that no constants get placed in
393 // the SDA. (This of course breaks down if the user passes `-G <n>` to Clang...) We can't do
394 // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command
395 // line options in LLVM are shared globally. So just force this feature off. Lovely stuff.
396 result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data));
397 }
398
389 // https://github.com/llvm/llvm-project/issues/105978399 // https://github.com/llvm/llvm-project/issues/105978
390 if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) {400 if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) {
391 result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2));401 result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2));
src/codegen/llvm.zig+1
...@@ -12444,6 +12444,7 @@ fn backendSupportsF80(target: std.Target) bool {...@@ -12444,6 +12444,7 @@ fn backendSupportsF80(target: std.Target) bool {
12444/// if it produces miscompilations.12444/// if it produces miscompilations.
12445fn backendSupportsF16(target: std.Target) bool {12445fn backendSupportsF16(target: std.Target) bool {
12446 return switch (target.cpu.arch) {12446 return switch (target.cpu.arch) {
12447 .hexagon,
12447 .powerpc,12448 .powerpc,
12448 .powerpcle,12449 .powerpcle,
12449 .powerpc64,12450 .powerpc64,
src/link/Elf.zig+1-1
...@@ -189,7 +189,7 @@ pub fn createEmpty(...@@ -189,7 +189,7 @@ pub fn createEmpty(
189 };189 };
190190
191 const page_size: u32 = switch (target.cpu.arch) {191 const page_size: u32 = switch (target.cpu.arch) {
192 .aarch64, .powerpc64le => 0x10000,192 .aarch64, .hexagon, .powerpc64le => 0x10000,
193 .sparc64 => 0x2000,193 .sparc64 => 0x2000,
194 else => 0x1000,194 else => 0x1000,
195 };195 };
tools/generate_linux_syscalls.zig+2
...@@ -22,6 +22,8 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{...@@ -22,6 +22,8 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
22 // ARM EABI/Thumb.22 // ARM EABI/Thumb.
23 .{ "arm_sync_file_range", "sync_file_range" },23 .{ "arm_sync_file_range", "sync_file_range" },
24 .{ "arm_fadvise64_64", "fadvise64_64" },24 .{ "arm_fadvise64_64", "fadvise64_64" },
25 // ARC and Hexagon.
26 .{ "mmap_pgoff", "mmap2" },
25});27});
2628
27// Only for newer architectures where we use the C preprocessor.29// Only for newer architectures where we use the C preprocessor.