freebsd-unwind.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* DWARF2 EH unwinding support for FreeBSD/ARM64 (aarch64).
  2. Copyright (C) 2017-2022 Free Software Foundation, Inc.
  3. Contributed by John Marino <gnugcc@marino.st>
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. GCC is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. /* Identify a signal frame, and set the frame state data appropriately.
  21. See unwind-dw2.c for the structs. */
  22. /* Always include AArch64 unwinder header file. */
  23. #include "config/aarch64/aarch64-unwind.h"
  24. #include <sys/types.h>
  25. #include <signal.h>
  26. #include <unistd.h>
  27. #include <sys/ucontext.h>
  28. #include <machine/frame.h>
  29. #include <sys/user.h>
  30. #include <sys/sysctl.h>
  31. #define REG_NAME(reg) mc_gpregs.gp_## reg
  32. #define XREG(num) mc_gpregs.gp_x[num]
  33. #define DARC __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__
  34. #define MD_FALLBACK_FRAME_STATE_FOR aarch64_freebsd_fallback_frame_state
  35. static int
  36. aarch64_outside_sigtramp_range (unsigned char *pc)
  37. {
  38. static int sigtramp_range_determined = 0;
  39. static unsigned char *sigtramp_start, *sigtramp_end;
  40. if (sigtramp_range_determined == 0)
  41. {
  42. struct kinfo_sigtramp kst = {0};
  43. size_t len = sizeof (kst);
  44. int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid() };
  45. sigtramp_range_determined = 1;
  46. if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0)
  47. {
  48. sigtramp_range_determined = 2;
  49. sigtramp_start = kst.ksigtramp_start;
  50. sigtramp_end = kst.ksigtramp_end;
  51. }
  52. }
  53. if (sigtramp_range_determined < 2) /* sysctl failed if < 2 */
  54. return 1;
  55. return (pc < sigtramp_start || pc >= sigtramp_end);
  56. }
  57. static _Unwind_Reason_Code
  58. aarch64_freebsd_fallback_frame_state
  59. (struct _Unwind_Context *context, _Unwind_FrameState *fs)
  60. {
  61. int n;
  62. struct sigframe *sf;
  63. mcontext_t *sc;
  64. _Unwind_Ptr new_cfa;
  65. if (aarch64_outside_sigtramp_range(context->ra))
  66. return _URC_END_OF_STACK;
  67. sf = (struct sigframe *) context->cfa;
  68. sc = &sf->sf_uc.uc_mcontext;
  69. new_cfa = (_Unwind_Ptr) sc;
  70. fs->regs.cfa_how = CFA_REG_OFFSET;
  71. fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
  72. fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
  73. for (n = 0; n < 32; n++)
  74. fs->regs.reg[n].how = REG_SAVED_OFFSET;
  75. for (n = 0; n < 30; n++)
  76. fs->regs.reg[n].loc.offset = (_Unwind_Ptr) &(sc->XREG(n)) - new_cfa;
  77. fs->regs.reg[30].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(lr)) - new_cfa;
  78. fs->regs.reg[31].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(sp)) - new_cfa;
  79. fs->regs.reg[DARC].how = REG_SAVED_OFFSET;
  80. fs->regs.reg[DARC].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(elr)) - new_cfa;
  81. fs->retaddr_column = DARC;
  82. fs->signal_frame = 1;
  83. return _URC_NO_REASON;
  84. }