| author | |
| committer | |
| log | be5378b03805fa95b3cf36b6727d2c364c155e64 |
| tree | e6571591425e1cf8e373a9663010de536b644148 |
| parent | 008bb1f1201a4b4987bf00de9daf46185aa9292d |
| parent | 45644b7e152e851b9f9f51095e3ce1ca7fcc8a56 |
| signature |
Some initial `hexagon-linux` port work15 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, |
| 435 | 435 | ||
| 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#L7 | 440 | // - 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#L7 | 441 | // - 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#L7 | 442 | // - 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#L9 | 443 | // - 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#L7 | 444 | // - 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#L14 | 445 | // - 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) { |
| 37 | const arch_bits = switch (native_arch) { | 37 | const 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; |
| 116 | pub const getcontext = arch_bits.getcontext; | 117 | pub const getcontext = arch_bits.getcontext; |
| 117 | 118 | ||
| 118 | pub const tls = @import("linux/tls.zig"); | 119 | pub const tls = @import("linux/tls.zig"); |
| 119 | pub const pie = @import("linux/start_pie.zig"); | 120 | pub const pie = @import("linux/pie.zig"); |
| 120 | pub const BPF = @import("linux/bpf.zig"); | 121 | pub const BPF = @import("linux/bpf.zig"); |
| 121 | pub const IOCTL = @import("linux/ioctl.zig"); | 122 | pub const IOCTL = @import("linux/ioctl.zig"); |
| 122 | pub const SECCOMP = @import("linux/seccomp.zig"); | 123 | pub 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 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | const maxInt = std.math.maxInt; | ||
| 3 | const linux = std.os.linux; | ||
| 4 | const SYS = linux.SYS; | ||
| 5 | const socklen_t = linux.socklen_t; | ||
| 6 | const sockaddr = linux.sockaddr; | ||
| 7 | const iovec = std.posix.iovec; | ||
| 8 | const iovec_const = std.posix.iovec_const; | ||
| 9 | const uid_t = linux.uid_t; | ||
| 10 | const gid_t = linux.gid_t; | ||
| 11 | const pid_t = linux.pid_t; | ||
| 12 | const stack_t = linux.stack_t; | ||
| 13 | const sigset_t = linux.sigset_t; | ||
| 14 | const timespec = std.os.linux.timespec; | ||
| 15 | |||
| 16 | pub 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 | |||
| 24 | pub 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 | |||
| 33 | pub 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 | |||
| 43 | pub 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 | |||
| 54 | pub 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 | |||
| 66 | pub 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 | |||
| 79 | pub 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 | |||
| 101 | pub 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 | |||
| 131 | pub const restore = restore_rt; | ||
| 132 | |||
| 133 | pub 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 | |||
| 151 | pub 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 | |||
| 177 | pub const VDSO = struct { | ||
| 178 | pub const CGT_SYM = "__kernel_clock_gettime"; | ||
| 179 | pub const CGT_VER = "LINUX_2.6.39"; | ||
| 180 | }; | ||
| 181 | |||
| 182 | pub 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 | |||
| 191 | pub 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 | |||
| 203 | pub 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 | |||
| 215 | pub const blksize_t = i32; | ||
| 216 | pub const nlink_t = u32; | ||
| 217 | pub const time_t = isize; | ||
| 218 | pub const mode_t = u32; | ||
| 219 | pub const off_t = isize; | ||
| 220 | pub const ino_t = usize; | ||
| 221 | pub const dev_t = usize; | ||
| 222 | pub const blkcnt_t = isize; | ||
| 223 | |||
| 224 | // The `stat` definition used by the Linux kernel. | ||
| 225 | pub 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 | |||
| 256 | pub const timeval = extern struct { | ||
| 257 | sec: isize, | ||
| 258 | usec: isize, | ||
| 259 | }; | ||
| 260 | |||
| 261 | pub const timezone = extern struct { | ||
| 262 | minuteswest: i32, | ||
| 263 | dsttime: i32, | ||
| 264 | }; | ||
| 265 | |||
| 266 | pub 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 | |||
| 277 | pub 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 | ||
| 286 | pub const getcontext = {}; | ||
| 287 | |||
| 288 | pub const Elf_Symndx = u32; | ||
lib/std/os/linux/arm-eabi.zig deleted-344| ... | @@ -1,344 +0,0 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | const maxInt = std.math.maxInt; | ||
| 3 | const linux = std.os.linux; | ||
| 4 | const SYS = linux.SYS; | ||
| 5 | const iovec = std.posix.iovec; | ||
| 6 | const iovec_const = std.posix.iovec_const; | ||
| 7 | const socklen_t = linux.socklen_t; | ||
| 8 | const stack_t = linux.stack_t; | ||
| 9 | const sigset_t = linux.sigset_t; | ||
| 10 | const uid_t = linux.uid_t; | ||
| 11 | const gid_t = linux.gid_t; | ||
| 12 | const pid_t = linux.pid_t; | ||
| 13 | const sockaddr = linux.sockaddr; | ||
| 14 | const timespec = linux.timespec; | ||
| 15 | |||
| 16 | pub 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 | |||
| 24 | pub 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 | |||
| 33 | pub 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 | |||
| 43 | pub 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 | |||
| 54 | pub 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 | |||
| 66 | pub 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 | |||
| 79 | pub 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 | |||
| 101 | pub 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 | |||
| 132 | pub 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 | |||
| 150 | pub 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 | |||
| 168 | pub const MMAP2_UNIT = 4096; | ||
| 169 | |||
| 170 | pub 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 | |||
| 196 | pub const VDSO = struct { | ||
| 197 | pub const CGT_SYM = "__vdso_clock_gettime"; | ||
| 198 | pub const CGT_VER = "LINUX_2.6"; | ||
| 199 | }; | ||
| 200 | |||
| 201 | pub 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 | |||
| 227 | pub 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 | |||
| 237 | pub 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 | |||
| 247 | pub 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 | |||
| 257 | pub const blksize_t = i32; | ||
| 258 | pub const nlink_t = u32; | ||
| 259 | pub const time_t = isize; | ||
| 260 | pub const mode_t = u32; | ||
| 261 | pub const off_t = i64; | ||
| 262 | pub const ino_t = u64; | ||
| 263 | pub const dev_t = u64; | ||
| 264 | pub const blkcnt_t = i64; | ||
| 265 | |||
| 266 | // The `stat` definition used by the Linux kernel. | ||
| 267 | pub 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 | |||
| 298 | pub const timeval = extern struct { | ||
| 299 | sec: i32, | ||
| 300 | usec: i32, | ||
| 301 | }; | ||
| 302 | |||
| 303 | pub const timezone = extern struct { | ||
| 304 | minuteswest: i32, | ||
| 305 | dsttime: i32, | ||
| 306 | }; | ||
| 307 | |||
| 308 | pub 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 | |||
| 332 | pub 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 | ||
| 342 | pub const getcontext = {}; | ||
| 343 | |||
| 344 | pub const Elf_Symndx = u32; | ||
lib/std/os/linux/arm.zig created+344| ... | @@ -0,0 +1,344 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | const maxInt = std.math.maxInt; | ||
| 3 | const linux = std.os.linux; | ||
| 4 | const SYS = linux.SYS; | ||
| 5 | const iovec = std.posix.iovec; | ||
| 6 | const iovec_const = std.posix.iovec_const; | ||
| 7 | const socklen_t = linux.socklen_t; | ||
| 8 | const stack_t = linux.stack_t; | ||
| 9 | const sigset_t = linux.sigset_t; | ||
| 10 | const uid_t = linux.uid_t; | ||
| 11 | const gid_t = linux.gid_t; | ||
| 12 | const pid_t = linux.pid_t; | ||
| 13 | const sockaddr = linux.sockaddr; | ||
| 14 | const timespec = linux.timespec; | ||
| 15 | |||
| 16 | pub 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 | |||
| 24 | pub 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 | |||
| 33 | pub 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 | |||
| 43 | pub 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 | |||
| 54 | pub 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 | |||
| 66 | pub 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 | |||
| 79 | pub 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 | |||
| 101 | pub 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 | |||
| 132 | pub 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 | |||
| 150 | pub 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 | |||
| 168 | pub const MMAP2_UNIT = 4096; | ||
| 169 | |||
| 170 | pub 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 | |||
| 196 | pub const VDSO = struct { | ||
| 197 | pub const CGT_SYM = "__vdso_clock_gettime"; | ||
| 198 | pub const CGT_VER = "LINUX_2.6"; | ||
| 199 | }; | ||
| 200 | |||
| 201 | pub 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 | |||
| 227 | pub 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 | |||
| 237 | pub 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 | |||
| 247 | pub 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 | |||
| 257 | pub const blksize_t = i32; | ||
| 258 | pub const nlink_t = u32; | ||
| 259 | pub const time_t = isize; | ||
| 260 | pub const mode_t = u32; | ||
| 261 | pub const off_t = i64; | ||
| 262 | pub const ino_t = u64; | ||
| 263 | pub const dev_t = u64; | ||
| 264 | pub const blkcnt_t = i64; | ||
| 265 | |||
| 266 | // The `stat` definition used by the Linux kernel. | ||
| 267 | pub 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 | |||
| 298 | pub const timeval = extern struct { | ||
| 299 | sec: i32, | ||
| 300 | usec: i32, | ||
| 301 | }; | ||
| 302 | |||
| 303 | pub const timezone = extern struct { | ||
| 304 | minuteswest: i32, | ||
| 305 | dsttime: i32, | ||
| 306 | }; | ||
| 307 | |||
| 308 | pub 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 | |||
| 332 | pub 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 | ||
| 342 | pub const getcontext = {}; | ||
| 343 | |||
| 344 | pub const Elf_Symndx = u32; | ||
lib/std/os/linux/arm64.zig deleted-288| ... | @@ -1,288 +0,0 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | const maxInt = std.math.maxInt; | ||
| 3 | const linux = std.os.linux; | ||
| 4 | const SYS = linux.SYS; | ||
| 5 | const socklen_t = linux.socklen_t; | ||
| 6 | const sockaddr = linux.sockaddr; | ||
| 7 | const iovec = std.posix.iovec; | ||
| 8 | const iovec_const = std.posix.iovec_const; | ||
| 9 | const uid_t = linux.uid_t; | ||
| 10 | const gid_t = linux.gid_t; | ||
| 11 | const pid_t = linux.pid_t; | ||
| 12 | const stack_t = linux.stack_t; | ||
| 13 | const sigset_t = linux.sigset_t; | ||
| 14 | const timespec = std.os.linux.timespec; | ||
| 15 | |||
| 16 | pub 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 | |||
| 24 | pub 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 | |||
| 33 | pub 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 | |||
| 43 | pub 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 | |||
| 54 | pub 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 | |||
| 66 | pub 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 | |||
| 79 | pub 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 | |||
| 101 | pub 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 | |||
| 131 | pub const restore = restore_rt; | ||
| 132 | |||
| 133 | pub 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 | |||
| 151 | pub 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 | |||
| 177 | pub const VDSO = struct { | ||
| 178 | pub const CGT_SYM = "__kernel_clock_gettime"; | ||
| 179 | pub const CGT_VER = "LINUX_2.6.39"; | ||
| 180 | }; | ||
| 181 | |||
| 182 | pub 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 | |||
| 191 | pub 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 | |||
| 203 | pub 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 | |||
| 215 | pub const blksize_t = i32; | ||
| 216 | pub const nlink_t = u32; | ||
| 217 | pub const time_t = isize; | ||
| 218 | pub const mode_t = u32; | ||
| 219 | pub const off_t = isize; | ||
| 220 | pub const ino_t = usize; | ||
| 221 | pub const dev_t = usize; | ||
| 222 | pub const blkcnt_t = isize; | ||
| 223 | |||
| 224 | // The `stat` definition used by the Linux kernel. | ||
| 225 | pub 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 | |||
| 256 | pub const timeval = extern struct { | ||
| 257 | sec: isize, | ||
| 258 | usec: isize, | ||
| 259 | }; | ||
| 260 | |||
| 261 | pub const timezone = extern struct { | ||
| 262 | minuteswest: i32, | ||
| 263 | dsttime: i32, | ||
| 264 | }; | ||
| 265 | |||
| 266 | pub 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 | |||
| 277 | pub 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 | ||
| 286 | pub const getcontext = {}; | ||
| 287 | |||
| 288 | pub const Elf_Symndx = u32; | ||
lib/std/os/linux/hexagon.zig created+254| ... | @@ -0,0 +1,254 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | const iovec = std.posix.iovec; | ||
| 3 | const iovec_const = std.posix.iovec_const; | ||
| 4 | const linux = std.os.linux; | ||
| 5 | const SYS = linux.SYS; | ||
| 6 | const uid_t = std.os.linux.uid_t; | ||
| 7 | const gid_t = std.os.linux.gid_t; | ||
| 8 | const pid_t = std.os.linux.pid_t; | ||
| 9 | const sockaddr = linux.sockaddr; | ||
| 10 | const socklen_t = linux.socklen_t; | ||
| 11 | const timespec = std.os.linux.timespec; | ||
| 12 | |||
| 13 | pub 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 | |||
| 21 | pub 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 | |||
| 30 | pub 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 | |||
| 40 | pub 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 | |||
| 51 | pub 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 | |||
| 63 | pub 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 | |||
| 76 | pub 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 | |||
| 98 | pub 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 | |||
| 130 | pub const restore = restore_rt; | ||
| 131 | |||
| 132 | pub 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 | |||
| 141 | pub 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 | |||
| 165 | pub const timeval = extern struct { | ||
| 166 | sec: time_t, | ||
| 167 | usec: i32, | ||
| 168 | }; | ||
| 169 | |||
| 170 | pub 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 | |||
| 179 | pub 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 | |||
| 191 | pub 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 | |||
| 203 | pub const blksize_t = i32; | ||
| 204 | pub const nlink_t = u32; | ||
| 205 | pub const time_t = i32; | ||
| 206 | pub const mode_t = u32; | ||
| 207 | pub const off_t = i64; | ||
| 208 | pub const ino_t = u64; | ||
| 209 | pub const dev_t = u64; | ||
| 210 | pub const blkcnt_t = i64; | ||
| 211 | |||
| 212 | // The `stat` definition used by the Linux kernel. | ||
| 213 | pub 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 | |||
| 244 | pub const Elf_Symndx = u32; | ||
| 245 | |||
| 246 | pub const MMAP2_UNIT = 4096; | ||
| 247 | |||
| 248 | pub const VDSO = void; | ||
| 249 | |||
| 250 | /// TODO | ||
| 251 | pub const ucontext_t = void; | ||
| 252 | |||
| 253 | /// TODO | ||
| 254 | pub const getcontext = {}; | ||
lib/std/os/linux/pie.zig created+304| ... | @@ -0,0 +1,304 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const elf = std.elf; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | |||
| 6 | const R_AMD64_RELATIVE = 8; | ||
| 7 | const R_386_RELATIVE = 8; | ||
| 8 | const R_ARC_RELATIVE = 56; | ||
| 9 | const R_ARM_RELATIVE = 23; | ||
| 10 | const R_AARCH64_RELATIVE = 1027; | ||
| 11 | const R_CSKY_RELATIVE = 9; | ||
| 12 | const R_HEXAGON_RELATIVE = 35; | ||
| 13 | const R_LARCH_RELATIVE = 3; | ||
| 14 | const R_68K_RELATIVE = 22; | ||
| 15 | const R_MIPS_RELATIVE = 128; | ||
| 16 | const R_PPC_RELATIVE = 22; | ||
| 17 | const R_RISCV_RELATIVE = 3; | ||
| 18 | const R_390_RELATIVE = 12; | ||
| 19 | const R_SPARC_RELATIVE = 22; | ||
| 20 | |||
| 21 | const 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. | ||
| 42 | inline 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 | |||
| 202 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const elf = std.elf; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | |||
| 6 | const R_AMD64_RELATIVE = 8; | ||
| 7 | const R_386_RELATIVE = 8; | ||
| 8 | const R_ARC_RELATIVE = 56; | ||
| 9 | const R_ARM_RELATIVE = 23; | ||
| 10 | const R_AARCH64_RELATIVE = 1027; | ||
| 11 | const R_CSKY_RELATIVE = 9; | ||
| 12 | const R_HEXAGON_RELATIVE = 35; | ||
| 13 | const R_LARCH_RELATIVE = 3; | ||
| 14 | const R_68K_RELATIVE = 22; | ||
| 15 | const R_MIPS_RELATIVE = 128; | ||
| 16 | const R_PPC_RELATIVE = 22; | ||
| 17 | const R_RISCV_RELATIVE = 3; | ||
| 18 | const R_390_RELATIVE = 12; | ||
| 19 | const R_SPARC_RELATIVE = 22; | ||
| 20 | |||
| 21 | const 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. | ||
| 42 | inline 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 | |||
| 202 | pub 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 | } |
| 143 | 143 | ||
| 144 | pub const clone = @import("arm-eabi.zig").clone; | 144 | pub const clone = @import("arm.zig").clone; |
| 145 | 145 | ||
| 146 | pub fn restore() callconv(.Naked) noreturn { | 146 | pub 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 | ); |
| 388 | 388 | ||
| 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/105978 | 399 | // 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. |
| 12445 | fn backendSupportsF16(target: std.Target) bool { | 12445 | fn 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 | }; |
| 190 | 190 | ||
| 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 | }); |
| 26 | 28 | ||
| 27 | // Only for newer architectures where we use the C preprocessor. | 29 | // Only for newer architectures where we use the C preprocessor. |