Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add effective user context manipulation routines #1127

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(kphp
VERSION 1.0.1
LANGUAGES CXX
LANGUAGES CXX ASM
DESCRIPTION "Compiler for PHP (aka KPHP)"
HOMEPAGE_URL https://github.com/VKCOM/kphp)

Expand Down
3 changes: 2 additions & 1 deletion common/common-tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ prepend(COMMON_TESTS_SOURCES ${COMMON_DIR}/
smart_ptrs/tagged-ptr-test.cpp
type_traits/list_of_types_test.cpp
wrappers/span-test.cpp
wrappers/string_view-test.cpp)
wrappers/string_view-test.cpp
ucontext/ucontext-portable-test.cpp)

prepare_cross_platform_libs(COMMON_TESTS_LIBS zstd)
set(COMMON_TESTS_LIBS vk::common_src vk::net_src vk::binlog_src vk::unicode ${COMMON_TESTS_LIBS} ${EPOLL_SHIM_LIB} OpenSSL::Crypto z)
Expand Down
9 changes: 8 additions & 1 deletion common/common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ prepend(COMMON_TL_METHODS_SOURCES ${COMMON_DIR}/tl/methods/

if (NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
prepend(COMMON_UCONTEXT_SOURCES ${COMMON_DIR}/ucontext/
ucontext-arm.cpp)
darwin/aarch64/context.cpp)
else()
prepend(COMMON_UCONTEXT_SOURCES ${COMMON_DIR}/ucontext/
linux/x86_64/startcontext.S
linux/x86_64/getcontext.S
linux/x86_64/setcontext.S
linux/x86_64/swapcontext.S
linux/x86_64/makecontext.cpp)
endif()

set(COMMON_ALL_SOURCES
Expand Down
8 changes: 8 additions & 0 deletions common/dl-utils-lite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ void dl_allow_all_signals () {
dl_passert (err != -1, "failed to allow all signals");
}

void dl_unblock_signal (int sig) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, sig);
int err = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
dl_passert (err != -1, "failed to unblock signal");
}

static void runtime_handler (const int sig, siginfo_t *info __attribute__((unused)), void *ucontext) {
fprintf (stderr, "%s caught, terminating program\n", strsignal(sig));
crash_dump_write(static_cast<ucontext_t *>(ucontext));
Expand Down
1 change: 1 addition & 0 deletions common/dl-utils-lite.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void dl_signal (int sig, void (*handler) (int));
void dl_restore_signal_mask ();
void dl_block_all_signals ();
void dl_allow_all_signals ();
void dl_unblock_signal (int sig);

void dl_print_backtrace(void **trace, int trace_size);
void dl_print_backtrace();
Expand Down
1 change: 1 addition & 0 deletions common/server/crash-dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "common/kprintf.h"
#include "common/ucontext/ucontext-portable.h"
#include <ucontext.h>

struct crash_dump_buffer {
char scratchpad[1024];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// Compiler for PHP (aka KPHP)
// libucontext (c) https://github.com/kaniini/libucontext/tree/master (copied as third-party and slightly modified)
// Copyright (c) 2023 LLC «V Kontakte»
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#include "common/ucontext/ucontext-arm.h"

#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>

#include "common/ucontext/darwin/aarch64/context.h"

enum { SP_OFFSET = 432, PC_OFFSET = 440, PSTATE_OFFSET = 448, FPSIMD_CONTEXT_OFFSET = 464 };

#define STR(x) #x
Expand All @@ -31,6 +30,8 @@ static_assert(offsetof(libucontext_ucontext, uc_mcontext.sp) == SP_OFFSET, "SP_O
static_assert(offsetof(libucontext_ucontext, uc_mcontext.pc) == PC_OFFSET, "PC_OFFSET is invalid");
static_assert(offsetof(libucontext_ucontext, uc_mcontext.pstate) == PSTATE_OFFSET, "PSTATE_OFFSET is invalid");

extern "C" int setcontext_portable(const libucontext_ucontext *);

__attribute__((visibility("hidden"))) void libucontext_trampoline() {
libucontext_ucontext *uc_link = nullptr;

Expand All @@ -40,10 +41,10 @@ __attribute__((visibility("hidden"))) void libucontext_trampoline() {
exit(0);
}

libucontext_setcontext(uc_link);
setcontext_portable(uc_link);
}

void libucontext_makecontext(libucontext_ucontext *ucp, void (*func)(), int argc, ...) {
extern "C" void makecontext_portable(libucontext_ucontext *ucp, void (*func)(), int argc, ...) {
unsigned long *sp;
unsigned long *regp;
va_list va;
Expand Down Expand Up @@ -73,27 +74,12 @@ void libucontext_makecontext(libucontext_ucontext *ucp, void (*func)(), int argc
va_end(va);
}

asm(".global " NAME(libucontext_getcontext) ";\n"
asm(".global " NAME(getcontext_portable) ";\n"
".align 2;\n"
NAME(libucontext_getcontext) ":\n"
NAME(getcontext_portable) ":\n"
"str xzr, [x0, #((184) + ((0) * (8)))]\n" // #REG_OFFSET(0)
/* save GPRs */
"stp x0, x1, [x0, #((184) + ((0) * (8)))]\n" // REG_OFFSET(0)
/* save x2 and x3 for reuse */
"stp x2, x3, [x0, #((184) + ((2) * (8)))]\n" // REG_OFFSET(2)
"stp x4, x5, [x0, #((184) + ((4) * (8)))]\n" // REG_OFFSET(4)
"stp x6, x7, [x0, #((184) + ((6) * (8)))]\n" // REG_OFFSET(6)
"stp x8, x9, [x0, #((184) + ((8) * (8)))]\n" // REG_OFFSET(8)
"stp x10, x11, [x0, #((184) + ((10) * (8)))]\n" // REG_OFFSET(10)
"stp x12, x13, [x0, #((184) + ((12) * (8)))]\n" // REG_OFFSET(12)
"stp x14, x15, [x0, #((184) + ((14) * (8)))]\n" // REG_OFFSET(14)
"stp x16, x17, [x0, #((184) + ((16) * (8)))]\n" // REG_OFFSET(16)
"stp x18, x19, [x0, #((184) + ((18) * (8)))]\n" // REG_OFFSET(18)
"stp x20, x21, [x0, #((184) + ((20) * (8)))]\n" // REG_OFFSET(20)
"stp x22, x23, [x0, #((184) + ((22) * (8)))]\n" // REG_OFFSET(22)
"stp x24, x25, [x0, #((184) + ((24) * (8)))]\n" // REG_OFFSET(24)
"stp x26, x27, [x0, #((184) + ((26) * (8)))]\n" // REG_OFFSET(26)
"stp x28, x29, [x0, #((184) + ((28) * (8)))]\n" // REG_OFFSET(28)
"str x30, [x0, #((184) + ((30) * (8)))]\n" // REG_OFFSET(30)
/* save current program counter in link register */
"str x30, [x0, #440]\n" // PC_OFFSET
/* save current stack pointer */
Expand All @@ -106,12 +92,30 @@ asm(".global " NAME(libucontext_getcontext) ";\n"
"stp q10, q11, [x2, #176]\n"
"stp q12, q13, [x2, #208]\n"
"stp q14, q15, [x2, #240]\n"
/* save GPRs and return value 0 */
"mov x2, x0\n"
"mov x0, #0\n"
"stp x0, x1, [x2, #((184) + ((0) * (8)))]\n" // REG_OFFSET(0)
/* x2 and x3 have already been saved */
"stp x4, x5, [x2, #((184) + ((4) * (8)))]\n" // REG_OFFSET(4)
"stp x6, x7, [x2, #((184) + ((6) * (8)))]\n" // REG_OFFSET(6)
"stp x8, x9, [x2, #((184) + ((8) * (8)))]\n" // REG_OFFSET(8)
"stp x10, x11, [x2, #((184) + ((10) * (8)))]\n" // REG_OFFSET(10)
"stp x12, x13, [x2, #((184) + ((12) * (8)))]\n" // REG_OFFSET(12)
"stp x14, x15, [x2, #((184) + ((14) * (8)))]\n" // REG_OFFSET(14)
"stp x16, x17, [x2, #((184) + ((16) * (8)))]\n" // REG_OFFSET(16)
"stp x18, x19, [x2, #((184) + ((18) * (8)))]\n" // REG_OFFSET(18)
"stp x20, x21, [x2, #((184) + ((20) * (8)))]\n" // REG_OFFSET(20)
"stp x22, x23, [x2, #((184) + ((22) * (8)))]\n" // REG_OFFSET(22)
"stp x24, x25, [x2, #((184) + ((24) * (8)))]\n" // REG_OFFSET(24)
"stp x26, x27, [x2, #((184) + ((26) * (8)))]\n" // REG_OFFSET(26)
"stp x28, x29, [x2, #((184) + ((28) * (8)))]\n" // REG_OFFSET(28)
"str x30, [x2, #((184) + ((30) * (8)))]\n" // REG_OFFSET(30)
"ret\n");

asm(".global " NAME(libucontext_setcontext) ";\n"
asm(".global " NAME(setcontext_portable) ";\n"
".align 2;\n"
NAME(libucontext_setcontext) ":\n"
NAME(setcontext_portable) ":\n"
/* restore GPRs */
"ldp x18, x19, [x0, #((184) + ((18) * (8)))]\n" // REG_OFFSET(18)
"ldp x20, x21, [x0, #((184) + ((20) * (8)))]\n" // REG_OFFSET(20)
Expand All @@ -138,9 +142,9 @@ asm(".global " NAME(libucontext_setcontext) ";\n"
/* jump to new PC */
"br x16\n");

asm(".global " NAME(libucontext_swapcontext) ";\n"
asm(".global " NAME(swapcontext_portable) ";\n"
".align 2;\n"
NAME(libucontext_swapcontext) ":\n"
NAME(swapcontext_portable) ":\n"
"str xzr, [x0, #((184) + ((0) * (8)))]\n" // REG_OFFSET(0)
/* save GPRs */
"stp x2, x3, [x0, #((184) + ((2) * (8)))]\n" // REG_OFFSET(2)
Expand Down Expand Up @@ -175,7 +179,7 @@ asm(".global " NAME(libucontext_swapcontext) ";\n"
"mov x28, x30\n"
/* move x1 to x0 and call setcontext */
"mov x0, x1\n"
"bl " NAME(libucontext_setcontext) "\n"
"bl " NAME(setcontext_portable) "\n"
/* hmm, we came back here try to return */
"mov x30, x28\n"
"ret\n");
54 changes: 54 additions & 0 deletions common/ucontext/darwin/aarch64/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2018-2022 Ariadne Conill <[email protected]>
// https://github.com/kaniini/libucontext/tree/master (copied as third-party and slightly modified)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#pragma once

#include <cstddef>

struct libucontext_mcontext {
unsigned long fault_address;
unsigned long regs[29];
unsigned long fp, lr, sp, pc, pstate;
long double __reserved[256];
};

struct libucontext_stack {
void *ss_sp;
int ss_flags;
size_t ss_size;
};

struct libucontext_ucontext {
unsigned long uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack uc_stack;
unsigned char __pad[136];
libucontext_mcontext uc_mcontext;
};

inline constexpr void *get_context_stack_ptr_portable(const libucontext_ucontext &ctx) noexcept {
return ctx.uc_stack.ss_sp;
}

inline constexpr size_t get_context_stack_size_portable(const libucontext_ucontext &ctx) noexcept {
return ctx.uc_stack.ss_size;
}

inline constexpr void set_context_stack_ptr_portable(libucontext_ucontext &ctx, void *sp) noexcept {
ctx.uc_stack.ss_sp = sp;
}

inline constexpr void set_context_stack_size_portable(libucontext_ucontext &ctx, size_t size) noexcept {
ctx.uc_stack.ss_size = size;
}

inline constexpr void set_context_link_portable(libucontext_ucontext &ctx, libucontext_ucontext *link) noexcept {
ctx.uc_link = link;
}

inline void *get_context_stack_base_ptr_portable(const libucontext_ucontext &ctx) noexcept {
return reinterpret_cast<void *>(ctx.uc_mcontext.fp);
}
29 changes: 29 additions & 0 deletions common/ucontext/darwin/x86_64/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#include <ucontext.h>

inline constexpr void *get_context_stack_ptr_portable(const ucontext_t &ctx) noexcept {
return ctx.uc_stack.ss_sp;
}

inline constexpr size_t get_context_stack_size_portable(const ucontext_t &ctx) noexcept {
return ctx.uc_stack.ss_size;
}

inline constexpr void set_context_stack_ptr_portable(ucontext_t &ctx, void *sp) noexcept {
ctx.uc_stack.ss_sp = sp;
}

inline constexpr void set_context_stack_size_portable(ucontext_t &ctx, size_t size) noexcept {
ctx.uc_stack.ss_size = size;
}

inline constexpr void set_context_link_portable(ucontext_t &ctx, ucontext_t *link) noexcept {
ctx.uc_link = link;
}

inline void *get_context_stack_base_ptr_portable(const ucontext_t &ctx) noexcept {
return reinterpret_cast<void *>(ctx.uc_mcontext->__ss.__rbp);
}
30 changes: 30 additions & 0 deletions common/ucontext/linux/aarch64/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2024 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#include <ucontext.h>

inline constexpr void *get_context_stack_ptr_portable(const ucontext_t &ctx) noexcept {
return ctx.uc_stack.ss_sp;
}

inline constexpr size_t get_context_stack_size_portable(const ucontext_t &ctx) noexcept {
return ctx.uc_stack.ss_size;
}

inline constexpr void set_context_stack_ptr_portable(ucontext_t &ctx, void *sp) noexcept {
ctx.uc_stack.ss_sp = sp;
}

inline constexpr void set_context_stack_size_portable(ucontext_t &ctx, size_t size) noexcept {
ctx.uc_stack.ss_size = size;
}

inline constexpr void set_context_link_portable(ucontext_t &ctx, ucontext_t *link) noexcept {
ctx.uc_link = link;
}

inline void *get_context_stack_base_ptr_portable(const ucontext_t &ctx) noexcept {
// 29 -- Frame Pointer, based on AArch64 spec
return reinterpret_cast<void *>(ctx.uc_mcontext.regs[29]);
}
Loading
Loading