std: Minor changes to startup code
* Smaller startup sequence for ppc64 * Terminate the frame-pointer chain when executing _start * Make the stack traces work on ppc64 * Make the stack traces coloured on ppc64, some ioctls numbers are different and the whole set of constants should be audited.
This commit is contained in:
parent
3ab4d112e0
commit
96fe971051
@ -327,9 +327,9 @@ pub fn writeStackTrace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const StackIterator = struct {
|
pub const StackIterator = struct {
|
||||||
// Skip every frame before this address is found
|
// Skip every frame before this address is found.
|
||||||
first_address: ?usize,
|
first_address: ?usize,
|
||||||
// Last known value of the frame pointer register
|
// Last known value of the frame pointer register.
|
||||||
fp: usize,
|
fp: usize,
|
||||||
|
|
||||||
pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
|
pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
|
||||||
@ -339,14 +339,19 @@ pub const StackIterator = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// On some architectures such as x86 the frame pointer is the address where
|
// Negative offset of the saved BP wrt the frame pointer.
|
||||||
// the previous fp is stored, while on some other architectures such as
|
|
||||||
// RISC-V it points to the "top" of the frame, just above where the previous
|
|
||||||
// fp and the return address are stored.
|
|
||||||
const fp_offset = if (builtin.arch.isRISCV())
|
const fp_offset = if (builtin.arch.isRISCV())
|
||||||
|
// On RISC-V the frame pointer points to the top of the saved register
|
||||||
|
// area, on pretty much every other architecture it points to the stack
|
||||||
|
// slot where the previous frame pointer is saved.
|
||||||
2 * @sizeOf(usize)
|
2 * @sizeOf(usize)
|
||||||
else
|
else
|
||||||
0;
|
0;
|
||||||
|
// Positive offset of the saved PC wrt the frame pointer.
|
||||||
|
const pc_offset = if (builtin.arch == .powerpc64le)
|
||||||
|
2 * @sizeOf(usize)
|
||||||
|
else
|
||||||
|
@sizeOf(usize);
|
||||||
|
|
||||||
pub fn next(self: *StackIterator) ?usize {
|
pub fn next(self: *StackIterator) ?usize {
|
||||||
var address = self.next_internal() orelse return null;
|
var address = self.next_internal() orelse return null;
|
||||||
@ -364,7 +369,7 @@ pub const StackIterator = struct {
|
|||||||
fn next_internal(self: *StackIterator) ?usize {
|
fn next_internal(self: *StackIterator) ?usize {
|
||||||
const fp = math.sub(usize, self.fp, fp_offset) catch return null;
|
const fp = math.sub(usize, self.fp, fp_offset) catch return null;
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check.
|
||||||
if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
|
if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -373,11 +378,14 @@ pub const StackIterator = struct {
|
|||||||
// Sanity check: the stack grows down thus all the parent frames must be
|
// Sanity check: the stack grows down thus all the parent frames must be
|
||||||
// be at addresses that are greater (or equal) than the previous one.
|
// be at addresses that are greater (or equal) than the previous one.
|
||||||
// A zero frame pointer often signals this is the last frame, that case
|
// A zero frame pointer often signals this is the last frame, that case
|
||||||
// is gracefully handled by the next call to next_internal
|
// is gracefully handled by the next call to next_internal.
|
||||||
if (new_fp != 0 and new_fp < self.fp)
|
if (new_fp != 0 and new_fp < self.fp)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const new_pc = @intToPtr(*const usize, fp + @sizeOf(usize)).*;
|
const new_pc = @intToPtr(
|
||||||
|
*const usize,
|
||||||
|
math.add(usize, fp, pc_offset) catch return null,
|
||||||
|
).*;
|
||||||
|
|
||||||
self.fp = new_fp;
|
self.fp = new_fp;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ pub usingnamespace @import("linux/prctl.zig");
|
|||||||
pub usingnamespace @import("linux/securebits.zig");
|
pub usingnamespace @import("linux/securebits.zig");
|
||||||
|
|
||||||
const is_mips = builtin.arch.isMIPS();
|
const is_mips = builtin.arch.isMIPS();
|
||||||
|
const is_ppc64 = builtin.arch.isPPC64();
|
||||||
|
|
||||||
pub const pid_t = i32;
|
pub const pid_t = i32;
|
||||||
pub const fd_t = i32;
|
pub const fd_t = i32;
|
||||||
@ -540,8 +541,8 @@ pub const TIOCGPGRP = 0x540F;
|
|||||||
pub const TIOCSPGRP = 0x5410;
|
pub const TIOCSPGRP = 0x5410;
|
||||||
pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411;
|
pub const TIOCOUTQ = if (is_mips) 0x7472 else 0x5411;
|
||||||
pub const TIOCSTI = 0x5412;
|
pub const TIOCSTI = 0x5412;
|
||||||
pub const TIOCGWINSZ = if (is_mips) 0x40087468 else 0x5413;
|
pub const TIOCGWINSZ = if (is_mips or is_ppc64) 0x40087468 else 0x5413;
|
||||||
pub const TIOCSWINSZ = if (is_mips) 0x80087467 else 0x5414;
|
pub const TIOCSWINSZ = if (is_mips or is_ppc64) 0x80087467 else 0x5414;
|
||||||
pub const TIOCMGET = 0x5415;
|
pub const TIOCMGET = 0x5415;
|
||||||
pub const TIOCMBIS = 0x5416;
|
pub const TIOCMBIS = 0x5416;
|
||||||
pub const TIOCMBIC = 0x5417;
|
pub const TIOCMBIC = 0x5417;
|
||||||
|
@ -102,46 +102,49 @@ fn _start() callconv(.Naked) noreturn {
|
|||||||
|
|
||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
.x86_64 => {
|
.x86_64 => {
|
||||||
starting_stack_ptr = asm (""
|
starting_stack_ptr = asm volatile (
|
||||||
|
\\ xor %%rbp, %%rbp
|
||||||
: [argc] "={rsp}" (-> [*]usize)
|
: [argc] "={rsp}" (-> [*]usize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.i386 => {
|
.i386 => {
|
||||||
starting_stack_ptr = asm (""
|
starting_stack_ptr = asm volatile (
|
||||||
|
\\ xor %%ebp, %%ebp
|
||||||
: [argc] "={esp}" (-> [*]usize)
|
: [argc] "={esp}" (-> [*]usize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.aarch64, .aarch64_be, .arm => {
|
.aarch64, .aarch64_be, .arm, .armeb => {
|
||||||
starting_stack_ptr = asm ("mov %[argc], sp"
|
starting_stack_ptr = asm volatile (
|
||||||
: [argc] "=r" (-> [*]usize)
|
\\ mov fp, #0
|
||||||
|
\\ mov lr, #0
|
||||||
|
: [argc] "={sp}" (-> [*]usize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.riscv64 => {
|
.riscv64 => {
|
||||||
starting_stack_ptr = asm ("mv %[argc], sp"
|
starting_stack_ptr = asm volatile (
|
||||||
: [argc] "=r" (-> [*]usize)
|
\\ li s0, 0
|
||||||
|
\\ li ra, 0
|
||||||
|
: [argc] "={sp}" (-> [*]usize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.mips, .mipsel => {
|
.mips, .mipsel => {
|
||||||
// Need noat here because LLVM is free to pick any register
|
// The lr is already zeroed on entry, as specified by the ABI.
|
||||||
starting_stack_ptr = asm (
|
starting_stack_ptr = asm volatile (
|
||||||
\\ .set noat
|
\\ move $fp, $0
|
||||||
\\ move %[argc], $sp
|
: [argc] "={sp}" (-> [*]usize)
|
||||||
: [argc] "=r" (-> [*]usize)
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.powerpc64le => {
|
.powerpc64le => {
|
||||||
// Before returning the stack pointer, we have to set up a backchain
|
// Setup the initial stack frame and clear the back chain pointer.
|
||||||
// and a few other registers required by the ELFv2 ABI.
|
|
||||||
// TODO: Support powerpc64 (big endian) on ELFv2.
|
// TODO: Support powerpc64 (big endian) on ELFv2.
|
||||||
starting_stack_ptr = asm (
|
starting_stack_ptr = asm volatile (
|
||||||
\\ mr 4, 1
|
\\ mr 4, 1
|
||||||
\\ subi 1, 1, 32
|
\\ li 0, 0
|
||||||
\\ li 5, 0
|
\\ stdu 0, -32(1)
|
||||||
\\ std 5, 0(1)
|
\\ mtlr 0
|
||||||
\\ mr %[argc], 4
|
: [argc] "={r4}" (-> [*]usize)
|
||||||
: [argc] "=r" (-> [*]usize)
|
|
||||||
:
|
:
|
||||||
: "r4", "r5"
|
: "r0"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
else => @compileError("unsupported arch"),
|
else => @compileError("unsupported arch"),
|
||||||
|
@ -735,6 +735,13 @@ pub const Target = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isPPC64(arch: Arch) bool {
|
||||||
|
return switch (arch) {
|
||||||
|
.powerpc64, .powerpc64le => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
|
pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
|
||||||
for (arch.allCpuModels()) |cpu| {
|
for (arch.allCpuModels()) |cpu| {
|
||||||
if (mem.eql(u8, cpu_name, cpu.name)) {
|
if (mem.eql(u8, cpu_name, cpu.name)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user