| author | |
| committer | |
| log | e02655798fbd97a069ee8be38a6eceac18335a4d |
| tree | 29cd77dacb2f60f1258cdfd6a7e00e7d52735d82 |
| parent | e6ac082437b87fccf6a7e592f813d3403427e512 |
| parent | 39e34081ca9ed3bee0b850bdbf44068b163d1062 |
| signature |
Some ppc64 stuff5 files changed, 54 insertions(+), 35 deletions(-)
lib/std/debug.zig+17-9| ... | ... | @@ -327,9 +327,9 @@ pub fn writeStackTrace( |
| 327 | 327 | } |
| 328 | 328 | |
| 329 | 329 | pub const StackIterator = struct { |
| 330 | // Skip every frame before this address is found | |
| 330 | // Skip every frame before this address is found. | |
| 331 | 331 | first_address: ?usize, |
| 332 | // Last known value of the frame pointer register | |
| 332 | // Last known value of the frame pointer register. | |
| 333 | 333 | fp: usize, |
| 334 | 334 | |
| 335 | 335 | pub fn init(first_address: ?usize, fp: ?usize) StackIterator { |
| ... | ... | @@ -339,14 +339,19 @@ pub const StackIterator = struct { |
| 339 | 339 | }; |
| 340 | 340 | } |
| 341 | 341 | |
| 342 | // On some architectures such as x86 the frame pointer is the address where | |
| 343 | // the previous fp is stored, while on some other architectures such as | |
| 344 | // RISC-V it points to the "top" of the frame, just above where the previous | |
| 345 | // fp and the return address are stored. | |
| 342 | // Negative offset of the saved BP wrt the frame pointer. | |
| 346 | 343 | const fp_offset = if (builtin.arch.isRISCV()) |
| 344 | // On RISC-V the frame pointer points to the top of the saved register | |
| 345 | // area, on pretty much every other architecture it points to the stack | |
| 346 | // slot where the previous frame pointer is saved. | |
| 347 | 347 | 2 * @sizeOf(usize) |
| 348 | 348 | else |
| 349 | 349 | 0; |
| 350 | // Positive offset of the saved PC wrt the frame pointer. | |
| 351 | const pc_offset = if (builtin.arch == .powerpc64le) | |
| 352 | 2 * @sizeOf(usize) | |
| 353 | else | |
| 354 | @sizeOf(usize); | |
| 350 | 355 | |
| 351 | 356 | pub fn next(self: *StackIterator) ?usize { |
| 352 | 357 | var address = self.next_internal() orelse return null; |
| ... | ... | @@ -364,7 +369,7 @@ pub const StackIterator = struct { |
| 364 | 369 | fn next_internal(self: *StackIterator) ?usize { |
| 365 | 370 | const fp = math.sub(usize, self.fp, fp_offset) catch return null; |
| 366 | 371 | |
| 367 | // Sanity check | |
| 372 | // Sanity check. | |
| 368 | 373 | if (fp == 0 or !mem.isAligned(fp, @alignOf(usize))) |
| 369 | 374 | return null; |
| 370 | 375 | |
| ... | ... | @@ -373,11 +378,14 @@ pub const StackIterator = struct { |
| 373 | 378 | // Sanity check: the stack grows down thus all the parent frames must be |
| 374 | 379 | // be at addresses that are greater (or equal) than the previous one. |
| 375 | 380 | // A zero frame pointer often signals this is the last frame, that case |
| 376 | // is gracefully handled by the next call to next_internal | |
| 381 | // is gracefully handled by the next call to next_internal. | |
| 377 | 382 | if (new_fp != 0 and new_fp < self.fp) |
| 378 | 383 | return null; |
| 379 | 384 | |
| 380 | const new_pc = @intToPtr(*const usize, fp + @sizeOf(usize)).*; | |
| 385 | const new_pc = @intToPtr( | |
| 386 | *const usize, | |
| 387 | math.add(usize, fp, pc_offset) catch return null, | |
| 388 | ).*; | |
| 381 | 389 | |
| 382 | 390 | self.fp = new_fp; |
| 383 | 391 |
lib/std/os/bits/linux.zig+3-2| ... | ... | @@ -29,6 +29,7 @@ pub usingnamespace @import("linux/prctl.zig"); |
| 29 | 29 | pub usingnamespace @import("linux/securebits.zig"); |
| 30 | 30 | |
| 31 | 31 | const is_mips = builtin.arch.isMIPS(); |
| 32 | const is_ppc64 = builtin.arch.isPPC64(); | |
| 32 | 33 | |
| 33 | 34 | pub const pid_t = i32; |
| 34 | 35 | pub const fd_t = i32; |
| ... | ... | @@ -540,8 +541,8 @@ pub const TIOCGPGRP = 0x540F; |
| 540 | 541 | pub const TIOCSPGRP = 0x5410; |
| 541 | 542 | pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411; |
| 542 | 543 | pub const TIOCSTI = 0x5412; |
| 543 | pub const TIOCGWINSZ = if (is_mips) 0x40087468 else 0x5413; | |
| 544 | pub const TIOCSWINSZ = if (is_mips) 0x80087467 else 0x5414; | |
| 544 | pub const TIOCGWINSZ = if (is_mips or is_ppc64) 0x40087468 else 0x5413; | |
| 545 | pub const TIOCSWINSZ = if (is_mips or is_ppc64) 0x80087467 else 0x5414; | |
| 545 | 546 | pub const TIOCMGET = 0x5415; |
| 546 | 547 | pub const TIOCMBIS = 0x5416; |
| 547 | 548 | pub const TIOCMBIC = 0x5417; |
lib/std/start.zig+24-21| ... | ... | @@ -102,46 +102,49 @@ fn _start() callconv(.Naked) noreturn { |
| 102 | 102 | |
| 103 | 103 | switch (builtin.arch) { |
| 104 | 104 | .x86_64 => { |
| 105 | starting_stack_ptr = asm ("" | |
| 105 | starting_stack_ptr = asm volatile ( | |
| 106 | \\ xor %%rbp, %%rbp | |
| 106 | 107 | : [argc] "={rsp}" (-> [*]usize) |
| 107 | 108 | ); |
| 108 | 109 | }, |
| 109 | 110 | .i386 => { |
| 110 | starting_stack_ptr = asm ("" | |
| 111 | starting_stack_ptr = asm volatile ( | |
| 112 | \\ xor %%ebp, %%ebp | |
| 111 | 113 | : [argc] "={esp}" (-> [*]usize) |
| 112 | 114 | ); |
| 113 | 115 | }, |
| 114 | .aarch64, .aarch64_be, .arm => { | |
| 115 | starting_stack_ptr = asm ("mov %[argc], sp" | |
| 116 | : [argc] "=r" (-> [*]usize) | |
| 116 | .aarch64, .aarch64_be, .arm, .armeb => { | |
| 117 | starting_stack_ptr = asm volatile ( | |
| 118 | \\ mov fp, #0 | |
| 119 | \\ mov lr, #0 | |
| 120 | : [argc] "={sp}" (-> [*]usize) | |
| 117 | 121 | ); |
| 118 | 122 | }, |
| 119 | 123 | .riscv64 => { |
| 120 | starting_stack_ptr = asm ("mv %[argc], sp" | |
| 121 | : [argc] "=r" (-> [*]usize) | |
| 124 | starting_stack_ptr = asm volatile ( | |
| 125 | \\ li s0, 0 | |
| 126 | \\ li ra, 0 | |
| 127 | : [argc] "={sp}" (-> [*]usize) | |
| 122 | 128 | ); |
| 123 | 129 | }, |
| 124 | 130 | .mips, .mipsel => { |
| 125 | // Need noat here because LLVM is free to pick any register | |
| 126 | starting_stack_ptr = asm ( | |
| 127 | \\ .set noat | |
| 128 | \\ move %[argc], $sp | |
| 129 | : [argc] "=r" (-> [*]usize) | |
| 131 | // The lr is already zeroed on entry, as specified by the ABI. | |
| 132 | starting_stack_ptr = asm volatile ( | |
| 133 | \\ move $fp, $0 | |
| 134 | : [argc] "={sp}" (-> [*]usize) | |
| 130 | 135 | ); |
| 131 | 136 | }, |
| 132 | 137 | .powerpc64le => { |
| 133 | // Before returning the stack pointer, we have to set up a backchain | |
| 134 | // and a few other registers required by the ELFv2 ABI. | |
| 138 | // Setup the initial stack frame and clear the back chain pointer. | |
| 135 | 139 | // TODO: Support powerpc64 (big endian) on ELFv2. |
| 136 | starting_stack_ptr = asm ( | |
| 140 | starting_stack_ptr = asm volatile ( | |
| 137 | 141 | \\ mr 4, 1 |
| 138 | \\ subi 1, 1, 32 | |
| 139 | \\ li 5, 0 | |
| 140 | \\ std 5, 0(1) | |
| 141 | \\ mr %[argc], 4 | |
| 142 | : [argc] "=r" (-> [*]usize) | |
| 142 | \\ li 0, 0 | |
| 143 | \\ stdu 0, -32(1) | |
| 144 | \\ mtlr 0 | |
| 145 | : [argc] "={r4}" (-> [*]usize) | |
| 143 | 146 | : |
| 144 | : "r4", "r5" | |
| 147 | : "r0" | |
| 145 | 148 | ); |
| 146 | 149 | }, |
| 147 | 150 | else => @compileError("unsupported arch"), |
lib/std/target.zig+7| ... | ... | @@ -754,6 +754,13 @@ pub const Target = struct { |
| 754 | 754 | }; |
| 755 | 755 | } |
| 756 | 756 | |
| 757 | pub fn isPPC64(arch: Arch) bool { | |
| 758 | return switch (arch) { | |
| 759 | .powerpc64, .powerpc64le => true, | |
| 760 | else => false, | |
| 761 | }; | |
| 762 | } | |
| 763 | ||
| 757 | 764 | pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { |
| 758 | 765 | for (arch.allCpuModels()) |cpu| { |
| 759 | 766 | if (mem.eql(u8, cpu_name, cpu.name)) { |
test/stack_traces.zig+3-3| ... | ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 282 | 282 | \\source.zig:10:8: [address] in main (test) |
| 283 | 283 | \\ foo(); |
| 284 | 284 | \\ ^ |
| 285 | \\start.zig:319:29: [address] in std.start.posixCallMainAndExit (test) | |
| 285 | \\start.zig:322:29: [address] in std.start.posixCallMainAndExit (test) | |
| 286 | 286 | \\ return root.main(); |
| 287 | 287 | \\ ^ |
| 288 | \\start.zig:151:5: [address] in std.start._start (test) | |
| 288 | \\start.zig:154:5: [address] in std.start._start (test) | |
| 289 | 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 290 | 290 | \\ ^ |
| 291 | 291 | \\ |
| ... | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 294 | 294 | switch (std.Target.current.cpu.arch) { |
| 295 | 295 | .aarch64 => "", // TODO disabled; results in segfault |
| 296 | 296 | else => |
| 297 | \\start.zig:151:5: [address] in std.start._start (test) | |
| 297 | \\start.zig:154:5: [address] in std.start._start (test) | |
| 298 | 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 299 | 299 | \\ ^ |
| 300 | 300 | \\ |