AutorÃa | Ultima modificación | Ver Log |
// Copyright 2019 Google//// 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 "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"#if defined(__arm__) || defined(__arm64__)#include <mach/arm/thread_status.h>#include <ptrauth.h>#endif#if CLS_CPU_X86_64#define GET_IP_REGISTER(r) (r->__ss.__rip)#define GET_FP_REGISTER(r) (r->__ss.__rbp)#define GET_SP_REGISTER(r) (r->__ss.__rsp)#define GET_LR_REGISTER(r) 0#define SET_IP_REGISTER(r, v) (r->__ss.__rip = v)#define SET_FP_REGISTER(r, v) (r->__ss.__rbp = v)#define SET_SP_REGISTER(r, v) (r->__ss.__rsp = v)#define SET_LR_REGISTER(r, v)#elif CLS_CPU_I386#define GET_IP_REGISTER(r) (r->__ss.__eip)#define GET_FP_REGISTER(r) (r->__ss.__ebp)#define GET_SP_REGISTER(r) (r->__ss.__esp)#define GET_LR_REGISTER(r) 0#define SET_IP_REGISTER(r, v) (r->__ss.__eip = v)#define SET_FP_REGISTER(r, v) (r->__ss.__ebp = v)#define SET_SP_REGISTER(r, v) (r->__ss.__esp = v)#define SET_LR_REGISTER(r, v)#elif CLS_CPU_ARM64// The arm_thread_state64_get_* macros translate down to the AUTIA and AUTIB instructions which// authenticate the address, but don't clear the upper bits. From the docs:// "If the authentication passes, the upper bits of the address are restored to enable// subsequent use of the address. the authentication fails, the upper bits are corrupted and// any subsequent use of the address results in a Translation fault."// Since we only want the address (with the metadata in the upper bits masked out), we used the// ptrauth_strip macro to clear the upper bits.//// We found later that ptrauth_strip doesn't seem to do anything. In many cases, the upper bits were// already stripped, so for most non-system-library code, Crashlytics would still symbolicate. But// for system libraries, the upper bits were being left in even when we called ptrauth_strip.// Instead, we're bit masking and only allowing the latter 36 bits.#define CLS_PTRAUTH_STRIP(pointer) ((uintptr_t)pointer & 0x0000000FFFFFFFFF)#define GET_IP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_pc(r->__ss)))#define GET_FP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_fp(r->__ss)))#define GET_SP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_sp(r->__ss)))#define GET_LR_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_lr(r->__ss)))#define SET_IP_REGISTER(r, v) arm_thread_state64_set_pc_fptr(r->__ss, (void*)v)#define SET_FP_REGISTER(r, v) arm_thread_state64_set_fp(r->__ss, v)#define SET_SP_REGISTER(r, v) arm_thread_state64_set_sp(r->__ss, v)#define SET_LR_REGISTER(r, v) arm_thread_state64_set_lr_fptr(r->__ss, (void*)v)#elif CLS_CPU_ARM#define GET_IP_REGISTER(r) (r->__ss.__pc)#define GET_FP_REGISTER(r) (r->__ss.__r[7])#define GET_SP_REGISTER(r) (r->__ss.__sp)#define GET_LR_REGISTER(r) (r->__ss.__lr)#define SET_IP_REGISTER(r, v) (r->__ss.__pc = v)#define SET_FP_REGISTER(r, v) (r->__ss.__r[7] = v)#define SET_SP_REGISTER(r, v) (r->__ss.__sp = v)#define SET_LR_REGISTER(r, v) (r->__ss.__lr = v)#else#error "Architecture Unsupported"#endifuintptr_t FIRCLSThreadContextGetPC(FIRCLSThreadContext* registers) {if (!registers) {return 0;}return GET_IP_REGISTER(registers);}uintptr_t FIRCLSThreadContextGetStackPointer(const FIRCLSThreadContext* registers) {if (!registers) {return 0;}return GET_SP_REGISTER(registers);}bool FIRCLSThreadContextSetStackPointer(FIRCLSThreadContext* registers, uintptr_t value) {if (!FIRCLSIsValidPointer(registers)) {return false;}SET_SP_REGISTER(registers, value);return true;}uintptr_t FIRCLSThreadContextGetLinkRegister(const FIRCLSThreadContext* registers) {if (!FIRCLSIsValidPointer(registers)) {return 0;}return GET_LR_REGISTER(registers);}bool FIRCLSThreadContextSetLinkRegister(FIRCLSThreadContext* registers, uintptr_t value) {if (!FIRCLSIsValidPointer(registers)) {return false;}SET_LR_REGISTER(registers, value);return true;}bool FIRCLSThreadContextSetPC(FIRCLSThreadContext* registers, uintptr_t value) {if (!registers) {return false;}SET_IP_REGISTER(registers, value);return true;}uintptr_t FIRCLSThreadContextGetFramePointer(const FIRCLSThreadContext* registers) {if (!FIRCLSIsValidPointer(registers)) {return 0;}return GET_FP_REGISTER(registers);}bool FIRCLSThreadContextSetFramePointer(FIRCLSThreadContext* registers, uintptr_t value) {if (!FIRCLSIsValidPointer(registers)) {return false;}SET_FP_REGISTER(registers, value);return true;}