1  /* Generic definitions for dealing with Mach thread states.
       2     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  
      20  /* Everything else is called `thread_state', but CMU's header file is
      21     called `thread_status'.  Oh boy.  */
      22  #include <mach/thread_status.h>
      23  
      24  /* The machine-dependent thread_state.h file can either define these
      25     macros, or just define PC and SP to the register names.  */
      26  
      27  #ifndef MACHINE_THREAD_STATE_SET_PC
      28  #define MACHINE_THREAD_STATE_SET_PC(ts, pc) \
      29    ((ts)->PC = (unsigned long int) (pc))
      30  #endif
      31  #ifndef MACHINE_THREAD_STATE_SET_SP
      32  #ifdef STACK_GROWTH_UP
      33  #define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \
      34    ((ts)->SP = (unsigned long int) (stack))
      35  #else
      36  #define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \
      37    ((ts)->SP = (unsigned long int) (stack) + (size))
      38  #endif
      39  #endif
      40  
      41  /* Set up the thread state to call the given function on the given state.
      42     Dependning on architecture, this may imply more than just setting PC
      43     and SP.  */
      44  #ifndef MACHINE_THREAD_STATE_SETUP_CALL
      45  #define MACHINE_THREAD_STATE_SETUP_CALL(ts, stack, size, func) \
      46    (MACHINE_THREAD_STATE_SET_PC (ts, func), \
      47     MACHINE_THREAD_STATE_SET_SP (ts, stack, size))
      48  #endif
      49  
      50  /* This copies architecture-specific bits from the current thread to the new
      51     thread state.  */
      52  #ifndef MACHINE_THREAD_STATE_FIX_NEW
      53  # define MACHINE_THREAD_STATE_FIX_NEW(ts)
      54  #endif
      55  
      56  /* These functions are of use in machine-dependent signal trampoline
      57     implementations.  */
      58  
      59  #include <string.h>		/* size_t, memcpy */
      60  #include <mach/mach_interface.h> /* __thread_get_state */
      61  
      62  static inline int
      63  machine_get_state (thread_t thread, struct machine_thread_all_state *state,
      64  		   int flavor, void *stateptr, void *scpptr, size_t size)
      65  {
      66    if (state->set & (1 << flavor))
      67      {
      68        /* Copy the saved state.  */
      69        memcpy (scpptr, stateptr, size);
      70        return 1;
      71      }
      72    else
      73      {
      74        /* No one asked about this flavor of state before; fetch the state
      75  	 directly from the kernel into the sigcontext.  */
      76        mach_msg_type_number_t got = (size / sizeof (int));
      77        return (! __thread_get_state (thread, flavor, scpptr, &got)
      78  	      && got == (size / sizeof (int)));
      79      }
      80  }
      81  
      82  static inline int
      83  machine_get_basic_state (thread_t thread,
      84  			 struct machine_thread_all_state *state)
      85  {
      86    mach_msg_type_number_t count;
      87  
      88    if (state->set & (1 << MACHINE_THREAD_STATE_FLAVOR))
      89      return 1;
      90  
      91    count = MACHINE_THREAD_STATE_COUNT;
      92    if (__thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR,
      93  			  (natural_t *) &state->basic,
      94  			  &count) != KERN_SUCCESS
      95        || count != MACHINE_THREAD_STATE_COUNT)
      96      /* What kind of thread?? */
      97      return 0;			/* XXX */
      98  
      99    state->set |= 1 << MACHINE_THREAD_STATE_FLAVOR;
     100    return 1;
     101  }