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(...@@ -327,9 +327,9 @@ pub fn writeStackTrace(
327}327}
328328
329pub const StackIterator = struct {329pub const StackIterator = struct {
330 // Skip every frame before this address is found330 // Skip every frame before this address is found.
331 first_address: ?usize,331 first_address: ?usize,
332 // Last known value of the frame pointer register332 // Last known value of the frame pointer register.
333 fp: usize,333 fp: usize,
334334
335 pub fn init(first_address: ?usize, fp: ?usize) StackIterator {335 pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
...@@ -339,14 +339,19 @@ pub const StackIterator = struct {...@@ -339,14 +339,19 @@ pub const StackIterator = struct {
339 };339 };
340 }340 }
341341
342 // On some architectures such as x86 the frame pointer is the address where342 // Negative offset of the saved BP wrt the frame pointer.
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.
346 const fp_offset = if (builtin.arch.isRISCV())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 2 * @sizeOf(usize)347 2 * @sizeOf(usize)
348 else348 else
349 0;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);
350355
351 pub fn next(self: *StackIterator) ?usize {356 pub fn next(self: *StackIterator) ?usize {
352 var address = self.next_internal() orelse return null;357 var address = self.next_internal() orelse return null;
...@@ -364,7 +369,7 @@ pub const StackIterator = struct {...@@ -364,7 +369,7 @@ pub const StackIterator = struct {
364 fn next_internal(self: *StackIterator) ?usize {369 fn next_internal(self: *StackIterator) ?usize {
365 const fp = math.sub(usize, self.fp, fp_offset) catch return null;370 const fp = math.sub(usize, self.fp, fp_offset) catch return null;
366371
367 // Sanity check372 // Sanity check.
368 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))373 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
369 return null;374 return null;
370375
...@@ -373,11 +378,14 @@ pub const StackIterator = struct {...@@ -373,11 +378,14 @@ pub const StackIterator = struct {
373 // Sanity check: the stack grows down thus all the parent frames must be378 // Sanity check: the stack grows down thus all the parent frames must be
374 // be at addresses that are greater (or equal) than the previous one.379 // be at addresses that are greater (or equal) than the previous one.
375 // A zero frame pointer often signals this is the last frame, that case380 // A zero frame pointer often signals this is the last frame, that case
376 // is gracefully handled by the next call to next_internal381 // is gracefully handled by the next call to next_internal.
377 if (new_fp != 0 and new_fp < self.fp)382 if (new_fp != 0 and new_fp < self.fp)
378 return null;383 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
382 self.fp = new_fp;390 self.fp = new_fp;
383391
lib/std/os/bits/linux.zig+3-2
...@@ -29,6 +29,7 @@ pub usingnamespace @import("linux/prctl.zig");...@@ -29,6 +29,7 @@ pub usingnamespace @import("linux/prctl.zig");
29pub usingnamespace @import("linux/securebits.zig");29pub usingnamespace @import("linux/securebits.zig");
3030
31const is_mips = builtin.arch.isMIPS();31const is_mips = builtin.arch.isMIPS();
32const is_ppc64 = builtin.arch.isPPC64();
3233
33pub const pid_t = i32;34pub const pid_t = i32;
34pub const fd_t = i32;35pub const fd_t = i32;
...@@ -540,8 +541,8 @@ pub const TIOCGPGRP = 0x540F;...@@ -540,8 +541,8 @@ pub const TIOCGPGRP = 0x540F;
540pub const TIOCSPGRP = 0x5410;541pub const TIOCSPGRP = 0x5410;
541pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411;542pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411;
542pub const TIOCSTI = 0x5412;543pub const TIOCSTI = 0x5412;
543pub const TIOCGWINSZ = if (is_mips) 0x40087468 else 0x5413;544pub const TIOCGWINSZ = if (is_mips or is_ppc64) 0x40087468 else 0x5413;
544pub const TIOCSWINSZ = if (is_mips) 0x80087467 else 0x5414;545pub const TIOCSWINSZ = if (is_mips or is_ppc64) 0x80087467 else 0x5414;
545pub const TIOCMGET = 0x5415;546pub const TIOCMGET = 0x5415;
546pub const TIOCMBIS = 0x5416;547pub const TIOCMBIS = 0x5416;
547pub const TIOCMBIC = 0x5417;548pub const TIOCMBIC = 0x5417;
lib/std/start.zig+24-21
...@@ -102,46 +102,49 @@ fn _start() callconv(.Naked) noreturn {...@@ -102,46 +102,49 @@ fn _start() callconv(.Naked) noreturn {
102102
103 switch (builtin.arch) {103 switch (builtin.arch) {
104 .x86_64 => {104 .x86_64 => {
105 starting_stack_ptr = asm (""105 starting_stack_ptr = asm volatile (
106 \\ xor %%rbp, %%rbp
106 : [argc] "={rsp}" (-> [*]usize)107 : [argc] "={rsp}" (-> [*]usize)
107 );108 );
108 },109 },
109 .i386 => {110 .i386 => {
110 starting_stack_ptr = asm (""111 starting_stack_ptr = asm volatile (
112 \\ xor %%ebp, %%ebp
111 : [argc] "={esp}" (-> [*]usize)113 : [argc] "={esp}" (-> [*]usize)
112 );114 );
113 },115 },
114 .aarch64, .aarch64_be, .arm => {116 .aarch64, .aarch64_be, .arm, .armeb => {
115 starting_stack_ptr = asm ("mov %[argc], sp"117 starting_stack_ptr = asm volatile (
116 : [argc] "=r" (-> [*]usize)118 \\ mov fp, #0
119 \\ mov lr, #0
120 : [argc] "={sp}" (-> [*]usize)
117 );121 );
118 },122 },
119 .riscv64 => {123 .riscv64 => {
120 starting_stack_ptr = asm ("mv %[argc], sp"124 starting_stack_ptr = asm volatile (
121 : [argc] "=r" (-> [*]usize)125 \\ li s0, 0
126 \\ li ra, 0
127 : [argc] "={sp}" (-> [*]usize)
122 );128 );
123 },129 },
124 .mips, .mipsel => {130 .mips, .mipsel => {
125 // Need noat here because LLVM is free to pick any register131 // The lr is already zeroed on entry, as specified by the ABI.
126 starting_stack_ptr = asm (132 starting_stack_ptr = asm volatile (
127 \\ .set noat133 \\ move $fp, $0
128 \\ move %[argc], $sp134 : [argc] "={sp}" (-> [*]usize)
129 : [argc] "=r" (-> [*]usize)
130 );135 );
131 },136 },
132 .powerpc64le => {137 .powerpc64le => {
133 // Before returning the stack pointer, we have to set up a backchain138 // Setup the initial stack frame and clear the back chain pointer.
134 // and a few other registers required by the ELFv2 ABI.
135 // TODO: Support powerpc64 (big endian) on ELFv2.139 // TODO: Support powerpc64 (big endian) on ELFv2.
136 starting_stack_ptr = asm (140 starting_stack_ptr = asm volatile (
137 \\ mr 4, 1141 \\ mr 4, 1
138 \\ subi 1, 1, 32142 \\ li 0, 0
139 \\ li 5, 0143 \\ stdu 0, -32(1)
140 \\ std 5, 0(1)144 \\ mtlr 0
141 \\ mr %[argc], 4145 : [argc] "={r4}" (-> [*]usize)
142 : [argc] "=r" (-> [*]usize)
143 :146 :
144 : "r4", "r5"147 : "r0"
145 );148 );
146 },149 },
147 else => @compileError("unsupported arch"),150 else => @compileError("unsupported arch"),
lib/std/target.zig+7
...@@ -754,6 +754,13 @@ pub const Target = struct {...@@ -754,6 +754,13 @@ pub const Target = struct {
754 };754 };
755 }755 }
756756
757 pub fn isPPC64(arch: Arch) bool {
758 return switch (arch) {
759 .powerpc64, .powerpc64le => true,
760 else => false,
761 };
762 }
763
757 pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {764 pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
758 for (arch.allCpuModels()) |cpu| {765 for (arch.allCpuModels()) |cpu| {
759 if (mem.eql(u8, cpu_name, cpu.name)) {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,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
282 \\source.zig:10:8: [address] in main (test)282 \\source.zig:10:8: [address] in main (test)
283 \\ foo();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 \\ return root.main();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 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});289 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
290 \\ ^290 \\ ^
291 \\291 \\
...@@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
294 switch (std.Target.current.cpu.arch) {294 switch (std.Target.current.cpu.arch) {
295 .aarch64 => "", // TODO disabled; results in segfault295 .aarch64 => "", // TODO disabled; results in segfault
296 else => 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 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});298 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
299 \\ ^299 \\ ^
300 \\300 \\