/* * Copyright (C) 2022 Apple Inc. All rights reserved. * * This document is the property of Apple Inc. * It is considered confidential and proprietary. * * This document may not be reproduced or transmitted in any form, * in whole or in part, without the express written permission of * Apple Inc. */ // TODO: Make this header visible to XNU #pragma once #include #include #include #include /** Size of the panic buffer (a single frame) */ #define XNUPROXY_PANIC_BUFFER_SIZE (1 << 16) /** Size reserved for descriptive string */ #define XNUPROXY_PANIC_MESSAGE_LEN 128 /** Alignment of the panic buffer (frame-aligned) */ #define XNUPROXY_PANIC_BUFFER_ALIGN XNUPROXY_PANIC_BUFFER_SIZE /** Space reserved for formatted panic message (first half of frame) */ #define XNUPROXY_PANIC_RENDERED_LEN (XNUPROXY_PANIC_BUFFER_SIZE / 2) /** Number of bytes reserved to store a process name */ #define XNUPROXY_PANIC_NAME_BYTES 64 /** Number of 32-bit words used to store the image UUID */ #define XNUPROXY_PANIC_UUID_BYTES (128 / CHAR_BIT) /** States of the panic buffer to indicate whether a panic occurred at cL4 user-level */ typedef enum : size_t { XNUPROXY_PANIC_UNSET = 0, XNUPROXY_PANIC_PARTIAL = 1, XNUPROXY_PANIC_COMPLETE = 2, } xnuproxy_panic_status_t; /** Four-character constant identifier */ typedef uint32_t xnuproxy_panic_four_cc_t; /** Structured information about panicked thread */ typedef struct { /** Status of the panic buffer */ _Atomic(xnuproxy_panic_four_cc_t) status; /** 64-bit identifier of address space in which the thread was executing */ uint64_t address_space_id; /** Component for which the thread was executing */ struct { /** Descriptive name of the process */ char name[XNUPROXY_PANIC_NAME_BYTES]; /** 64-bit identifier */ uint64_t numeric_id; /** 64-bit selector value */ uint64_t selector; } component; /** FourCC identifiers for thread */ struct { /** Address space */ xnuproxy_panic_four_cc_t space; /** Tightbeam component */ xnuproxy_panic_four_cc_t component; /** Endpoint to which panicked thread is bound */ xnuproxy_panic_four_cc_t endpoint; /** Panicked thread */ xnuproxy_panic_four_cc_t thread; } four_cc; /** Thread context data */ struct { /** Address of the thread structure */ size_t address; /** Address of the thread's TSS array */ size_t tss_base; /** Addres of the thread's IPC buffer */ size_t ipc_buffer; /** ID of the execution context */ size_t scheduling_context_id; /** ID of the execution context */ size_t execution_context_id; /** Numeric ID of the thread */ size_t thread_numeric_id; /** ID of the endpoint */ size_t endpoint_id; /** The thread's stack region */ struct { /** The lowest-value address of the stack region */ size_t start; /** The size of the stack region */ size_t size; /** The inital value of the call stack */ size_t call_base; } stack; /** Subset of the thread's registers */ struct { /** Link register */ size_t lr; /** Program counter */ size_t pc; /** Stack pointer */ size_t sp; /** Status register */ size_t cpsr; } registers; } thread; /** Backtrace bounds */ struct { /** Number of frame entries */ size_t frames; /** First index in image array */ size_t image_base; } backtrace; } xnuproxy_panicked_thread_t; /** Maximum size of backtrace in bytes */ #define XNUPROXY__PANIC_BACKTRACE_BYTES ( \ XNUPROXY_PANIC_BUFFER_SIZE - ( \ XNUPROXY_PANIC_RENDERED_LEN + \ XNUPROXY_PANIC_MESSAGE_LEN + \ sizeof(xnuproxy_panicked_thread_t) \ ) \ ) /** Image UUID from backtrace */ typedef struct { char uuid[XNUPROXY_PANIC_UUID_BYTES]; } xnuproxy_panic_backtrace_image_t; static_assert( sizeof(xnuproxy_panic_backtrace_image_t) == XNUPROXY_PANIC_UUID_BYTES, "Panic backtrace image is UUID sized" ); #define XNUPROXY__PANIC_BACKTRACE_IMAGES \ (XNUPROXY__PANIC_BACKTRACE_BYTES / sizeof(xnuproxy_panic_backtrace_image_t)) /** Return address from backtrace */ typedef struct { /** Offset of address in respective image */ uintptr_t offset : 48; /** Index into image array containing corresponding UUID */ uintptr_t image : 16; } xnuproxy_panic_backtrace_word_t; static_assert( sizeof(xnuproxy_panic_backtrace_word_t) == sizeof(uintptr_t), "Panic bactrace word is only one word" ); /** Maximum number of words of recorded backtrace */ #define XNUPROXY__PANIC_BACKTRACE_WORDS \ ( XNUPROXY__PANIC_BACKTRACE_BYTES / sizeof(xnuproxy_panic_backtrace_word_t)) /** Shared buffer of panic data with XNU */ typedef struct { /** Panic message */ _Alignas(XNUPROXY_PANIC_BUFFER_ALIGN) char rendered[XNUPROXY_PANIC_RENDERED_LEN]; /** formatted panic string */ char message[XNUPROXY_PANIC_MESSAGE_LEN]; /** Panicked thread state */ xnuproxy_panicked_thread_t panicked_thread; /** Backtrace of panicked thread */ union { /** Image UUIDS */ xnuproxy_panic_backtrace_image_t images[XNUPROXY__PANIC_BACKTRACE_IMAGES]; /** Bactrace words with references to images */ xnuproxy_panic_backtrace_word_t words[XNUPROXY__PANIC_BACKTRACE_WORDS]; } backtrace; } xnuproxy_panic_buffer_t; _Static_assert( _Alignof(xnuproxy_panic_buffer_t) == XNUPROXY_PANIC_BUFFER_ALIGN, "Panic buffer fits in frame" ); _Static_assert( sizeof(xnuproxy_panic_buffer_t) <= XNUPROXY_PANIC_BUFFER_SIZE, "Panic buffer fits in frame" );