blob: 7077c883b2f081c497af83e7e6ea160a7b5d6766 [file] [log] [blame]
// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/shared/pthread/thread_context_internal.h"
#if !defined(__linux__)
#error "SbThreadContext is only implemented for Linux"
#endif
#if !(SB_IS_32_BIT || SB_IS_64_BIT)
#error "CPU architecture must be either 32-bit or 64-bit"
#endif
// UCLIBC pretends to be GLIBC.
#if (defined(__GLIBC__) || defined(__GNU_LIBRARY__)) && !defined(__UCLIBC__)
#define SB_IS_GLIBC 1
#else
#define SB_IS_GLIBC 0
#endif
SbThreadContextPrivate::SbThreadContextPrivate(ucontext_t* ucontext) {
mcontext_t& mcontext = ucontext->uc_mcontext;
#if SB_IS_ARCH_X64
// 64-bit X86 (aka X64)
ip_ = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]);
sp_ = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]);
fp_ = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]);
#elif SB_IS_ARCH_X86
// 32-bit X86
ip_ = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]);
sp_ = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
fp_ = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
#elif SB_IS_ARCH_ARM64
// 64-bit ARM
ip_ = reinterpret_cast<void*>(mcontext.pc);
sp_ = reinterpret_cast<void*>(mcontext.sp);
fp_ = reinterpret_cast<void*>(mcontext.regs[29]);
lr_ = reinterpret_cast<void*>(mcontext.regs[30]);
#elif SB_IS_ARCH_ARM
#if SB_IS_GLIBC && ((__GLIBC__ * 100 + __GLIBC_MINOR__) < 204)
// 32-bit ARM w/ old GLIBC that used gregs[]
ip_ = reinterpret_cast<void*>(mcontext.gregs[R15]);
sp_ = reinterpret_cast<void*>(mcontext.gregs[R13]);
fp_ = reinterpret_cast<void*>(mcontext.gregs[R11]);
lr_ = reinterpret_cast<void*>(mcontext.gregs[R14]);
#else
// 32-bit ARM
ip_ = reinterpret_cast<void*>(mcontext.arm_pc);
sp_ = reinterpret_cast<void*>(mcontext.arm_sp);
fp_ = reinterpret_cast<void*>(mcontext.arm_fp);
lr_ = reinterpret_cast<void*>(mcontext.arm_lr);
#endif
#else // SB_IS_ARCH_XXX
#error "SbThreadContext isn't implemented for this CPU architecture"
#endif // SB_IS_ARCH_XXX
}