authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-22 17:39:26-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-22 17:39:26-04:00
loge02655798fbd97a069ee8be38a6eceac18335a4d
tree29cd77dacb2f60f1258cdfd6a7e00e7d52735d82
parente6ac082437b87fccf6a7e592f813d3403427e512
parent39e34081ca9ed3bee0b850bdbf44068b163d1062
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6743 from LemonBoy/someppc64stuff

Some ppc64 stuff

5 files changed, 54 insertions(+), 35 deletions(-)

lib/std/debug.zig+17-9
......@@ -327,9 +327,9 @@ pub fn writeStackTrace(
327327}
328328
329329pub const StackIterator = struct {
330 // Skip every frame before this address is found
330 // Skip every frame before this address is found.
331331 first_address: ?usize,
332 // Last known value of the frame pointer register
332 // Last known value of the frame pointer register.
333333 fp: usize,
334334
335335 pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
......@@ -339,14 +339,19 @@ pub const StackIterator = struct {
339339 };
340340 }
341341
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.
346343 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.
347347 2 * @sizeOf(usize)
348348 else
349349 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);
350355
351356 pub fn next(self: *StackIterator) ?usize {
352357 var address = self.next_internal() orelse return null;
......@@ -364,7 +369,7 @@ pub const StackIterator = struct {
364369 fn next_internal(self: *StackIterator) ?usize {
365370 const fp = math.sub(usize, self.fp, fp_offset) catch return null;
366371
367 // Sanity check
372 // Sanity check.
368373 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
369374 return null;
370375
......@@ -373,11 +378,14 @@ pub const StackIterator = struct {
373378 // Sanity check: the stack grows down thus all the parent frames must be
374379 // be at addresses that are greater (or equal) than the previous one.
375380 // 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.
377382 if (new_fp != 0 and new_fp < self.fp)
378383 return null;
379384
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 ).*;
381389
382390 self.fp = new_fp;
383391
lib/std/os/bits/linux.zig+3-2
......@@ -29,6 +29,7 @@ pub usingnamespace @import("linux/prctl.zig");
2929pub usingnamespace @import("linux/securebits.zig");
3030
3131const is_mips = builtin.arch.isMIPS();
32const is_ppc64 = builtin.arch.isPPC64();
3233
3334pub const pid_t = i32;
3435pub const fd_t = i32;
......@@ -540,8 +541,8 @@ pub const TIOCGPGRP = 0x540F;
540541pub const TIOCSPGRP = 0x5410;
541542pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411;
542543pub const TIOCSTI = 0x5412;
543pub const TIOCGWINSZ = if (is_mips) 0x40087468 else 0x5413;
544pub const TIOCSWINSZ = if (is_mips) 0x80087467 else 0x5414;
544pub const TIOCGWINSZ = if (is_mips or is_ppc64) 0x40087468 else 0x5413;
545pub const TIOCSWINSZ = if (is_mips or is_ppc64) 0x80087467 else 0x5414;
545546pub const TIOCMGET = 0x5415;
546547pub const TIOCMBIS = 0x5416;
547548pub const TIOCMBIC = 0x5417;
lib/std/start.zig+24-21
......@@ -102,46 +102,49 @@ fn _start() callconv(.Naked) noreturn {
102102
103103 switch (builtin.arch) {
104104 .x86_64 => {
105 starting_stack_ptr = asm (""
105 starting_stack_ptr = asm volatile (
106 \\ xor %%rbp, %%rbp
106107 : [argc] "={rsp}" (-> [*]usize)
107108 );
108109 },
109110 .i386 => {
110 starting_stack_ptr = asm (""
111 starting_stack_ptr = asm volatile (
112 \\ xor %%ebp, %%ebp
111113 : [argc] "={esp}" (-> [*]usize)
112114 );
113115 },
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)
117121 );
118122 },
119123 .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)
122128 );
123129 },
124130 .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)
130135 );
131136 },
132137 .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.
135139 // TODO: Support powerpc64 (big endian) on ELFv2.
136 starting_stack_ptr = asm (
140 starting_stack_ptr = asm volatile (
137141 \\ 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)
143146 :
144 : "r4", "r5"
147 : "r0"
145148 );
146149 },
147150 else => @compileError("unsupported arch"),
lib/std/target.zig+7
......@@ -754,6 +754,13 @@ pub const Target = struct {
754754 };
755755 }
756756
757 pub fn isPPC64(arch: Arch) bool {
758 return switch (arch) {
759 .powerpc64, .powerpc64le => true,
760 else => false,
761 };
762 }
763
757764 pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
758765 for (arch.allCpuModels()) |cpu| {
759766 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 {
282282 \\source.zig:10:8: [address] in main (test)
283283 \\ foo();
284284 \\ ^
285 \\start.zig:319:29: [address] in std.start.posixCallMainAndExit (test)
285 \\start.zig:322:29: [address] in std.start.posixCallMainAndExit (test)
286286 \\ return root.main();
287287 \\ ^
288 \\start.zig:151:5: [address] in std.start._start (test)
288 \\start.zig:154:5: [address] in std.start._start (test)
289289 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
290290 \\ ^
291291 \\
......@@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
294294 switch (std.Target.current.cpu.arch) {
295295 .aarch64 => "", // TODO disabled; results in segfault
296296 else =>
297 \\start.zig:151:5: [address] in std.start._start (test)
297 \\start.zig:154:5: [address] in std.start._start (test)
298298 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
299299 \\ ^
300300 \\