014-backport-mips-support-stack.patch 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. From f2acb06970522a9563d82490f2f1b8fc0bb5b720 Mon Sep 17 00:00:00 2001
  2. From: Ying Huang <[email protected]>
  3. Date: Tue, 5 Mar 2024 17:51:21 +0800
  4. Subject: [PATCH] stack: Fix stack unwind failure on mips
  5. Add abi_cfi, set_initial_registers_tid, unwind on mips.
  6. * backends/Makefile.am (mips_SRCS): Add mips_initreg.c,
  7. mips_cfi.c and mips_unwind.c.
  8. * backends/mips_init.c (mips_init): HOOK abi_cfi, unwind and
  9. set_initial_registers_tid. Set frame_nregs to 71.
  10. * backends/mips_cfi.c: New file.
  11. * backends/mips_initreg.c: Likewise.
  12. * backends/mips_unwind.c: Likewise.
  13. Signed-off-by: Ying Huang <[email protected]>
  14. ---
  15. backends/Makefile.am | 3 +-
  16. backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++
  17. backends/mips_init.c | 4 ++
  18. backends/mips_initreg.c | 61 ++++++++++++++++++++++++++++++
  19. backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++
  20. 5 files changed, 219 insertions(+), 1 deletion(-)
  21. create mode 100644 backends/mips_cfi.c
  22. create mode 100644 backends/mips_initreg.c
  23. create mode 100644 backends/mips_unwind.c
  24. --- a/backends/Makefile.am
  25. +++ b/backends/Makefile.am
  26. @@ -102,7 +102,8 @@ loongarch_SRCS = loongarch_init.c loonga
  27. arc_SRCS = arc_init.c arc_symbol.c
  28. -mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c
  29. +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \
  30. + mips_cfi.c mips_unwind.c
  31. libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
  32. $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
  33. --- /dev/null
  34. +++ b/backends/mips_cfi.c
  35. @@ -0,0 +1,68 @@
  36. +/* MIPS ABI-specified defaults for DWARF CFI.
  37. + Copyright (C) 2009 Red Hat, Inc.
  38. + Copyright (C) 2024 CIP United Inc.
  39. + This file is part of elfutils.
  40. +
  41. + This file is free software; you can redistribute it and/or modify
  42. + it under the terms of either
  43. +
  44. + * the GNU Lesser General Public License as published by the Free
  45. + Software Foundation; either version 3 of the License, or (at
  46. + your option) any later version
  47. +
  48. + or
  49. +
  50. + * the GNU General Public License as published by the Free
  51. + Software Foundation; either version 2 of the License, or (at
  52. + your option) any later version
  53. +
  54. + or both in parallel, as here.
  55. +
  56. + elfutils is distributed in the hope that it will be useful, but
  57. + WITHOUT ANY WARRANTY; without even the implied warranty of
  58. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  59. + General Public License for more details.
  60. +
  61. + You should have received copies of the GNU General Public License and
  62. + the GNU Lesser General Public License along with this program. If
  63. + not, see <http://www.gnu.org/licenses/>. */
  64. +
  65. +#ifdef HAVE_CONFIG_H
  66. +# include <config.h>
  67. +#endif
  68. +
  69. +#include <dwarf.h>
  70. +
  71. +#define BACKEND mips_
  72. +#include "libebl_CPU.h"
  73. +
  74. +int
  75. +mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
  76. +{
  77. + static const uint8_t abi_cfi[] =
  78. + {
  79. + DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0),
  80. + /* Callee-saved regs. */
  81. + DW_CFA_same_value, ULEB128_7 (16), /* s0 */
  82. + DW_CFA_same_value, ULEB128_7 (17), /* s1 */
  83. + DW_CFA_same_value, ULEB128_7 (18), /* s2 */
  84. + DW_CFA_same_value, ULEB128_7 (19), /* s3 */
  85. + DW_CFA_same_value, ULEB128_7 (20), /* s4 */
  86. + DW_CFA_same_value, ULEB128_7 (21), /* s5 */
  87. + DW_CFA_same_value, ULEB128_7 (22), /* s6 */
  88. + DW_CFA_same_value, ULEB128_7 (23), /* s7 */
  89. + DW_CFA_same_value, ULEB128_7 (28), /* gp */
  90. + DW_CFA_same_value, ULEB128_7 (29), /* sp */
  91. + DW_CFA_same_value, ULEB128_7 (30), /* fp */
  92. +
  93. + DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0),
  94. + };
  95. +
  96. + abi_info->initial_instructions = abi_cfi;
  97. + abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
  98. + abi_info->data_alignment_factor = 8;
  99. +
  100. + abi_info->return_address_register = 31; /* %ra */
  101. +
  102. + return 0;
  103. +}
  104. --- a/backends/mips_init.c
  105. +++ b/backends/mips_init.c
  106. @@ -58,5 +58,9 @@ mips_init (Elf *elf __attribute__ ((unus
  107. HOOK (eh, check_object_attribute);
  108. HOOK (eh, check_special_symbol);
  109. HOOK (eh, check_reloc_target_type);
  110. + HOOK (eh, set_initial_registers_tid);
  111. + HOOK (eh, abi_cfi);
  112. + HOOK (eh, unwind);
  113. + eh->frame_nregs = 71;
  114. return eh;
  115. }
  116. --- /dev/null
  117. +++ b/backends/mips_initreg.c
  118. @@ -0,0 +1,61 @@
  119. +/* Fetch live process registers from TID.
  120. + Copyright (C) 2024 CIP United Inc.
  121. + This file is part of elfutils.
  122. +
  123. + This file is free software; you can redistribute it and/or modify
  124. + it under the terms of either
  125. +
  126. + * the GNU Lesser General Public License as published by the Free
  127. + Software Foundation; either version 3 of the License, or (at
  128. + your option) any later version
  129. +
  130. + or
  131. +
  132. + * the GNU General Public License as published by the Free
  133. + Software Foundation; either version 2 of the License, or (at
  134. + your option) any later version
  135. +
  136. + or both in parallel, as here.
  137. +
  138. + elfutils is distributed in the hope that it will be useful, but
  139. + WITHOUT ANY WARRANTY; without even the implied warranty of
  140. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  141. + General Public License for more details.
  142. +
  143. + You should have received copies of the GNU General Public License and
  144. + the GNU Lesser General Public License along with this program. If
  145. + not, see <http://www.gnu.org/licenses/>. */
  146. +
  147. +#ifdef HAVE_CONFIG_H
  148. +# include <config.h>
  149. +#endif
  150. +
  151. +#include <stdlib.h>
  152. +#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__)
  153. +# include <sys/user.h>
  154. +# include <sys/ptrace.h>
  155. +#include <asm/ptrace.h>
  156. +#endif
  157. +
  158. +#define BACKEND mips_
  159. +#include "libebl_CPU.h"
  160. +
  161. +
  162. +bool
  163. +mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
  164. + ebl_tid_registers_t *setfunc __attribute__ ((unused)),
  165. + void *arg __attribute__ ((unused)))
  166. +{
  167. +#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__)
  168. + return false;
  169. +#else /* __mips__ */
  170. +/* For PTRACE_GETREGS */
  171. +
  172. + struct pt_regs gregs;
  173. + if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0)
  174. + return false;
  175. + if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg))
  176. + return false;
  177. + return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg);
  178. +#endif /* __mips__ */
  179. +}
  180. --- /dev/null
  181. +++ b/backends/mips_unwind.c
  182. @@ -0,0 +1,84 @@
  183. +/* Get previous frame state for an existing frame state.
  184. + Copyright (C) 2016 The Qt Company Ltd.
  185. + Copyright (C) 2024 CIP United Inc.
  186. + This file is part of elfutils.
  187. +
  188. + This file is free software; you can redistribute it and/or modify
  189. + it under the terms of either
  190. +
  191. + * the GNU Lesser General Public License as published by the Free
  192. + Software Foundation; either version 3 of the License, or (at
  193. + your option) any later version
  194. +
  195. + or
  196. +
  197. + * the GNU General Public License as published by the Free
  198. + Software Foundation; either version 2 of the License, or (at
  199. + your option) any later version
  200. +
  201. + or both in parallel, as here.
  202. +
  203. + elfutils is distributed in the hope that it will be useful, but
  204. + WITHOUT ANY WARRANTY; without even the implied warranty of
  205. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  206. + General Public License for more details.
  207. +
  208. + You should have received copies of the GNU General Public License and
  209. + the GNU Lesser General Public License along with this program. If
  210. + not, see <http://www.gnu.org/licenses/>. */
  211. +
  212. +#ifdef HAVE_CONFIG_H
  213. +# include <config.h>
  214. +#endif
  215. +
  216. +#define BACKEND mips_
  217. +#define SP_REG 29
  218. +#define FP_REG 30
  219. +#define LR_REG 31
  220. +#define FP_OFFSET 0
  221. +#define LR_OFFSET 8
  222. +#define SP_OFFSET 16
  223. +
  224. +#include "libebl_CPU.h"
  225. +
  226. +/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */
  227. +
  228. +bool
  229. +EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
  230. + ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
  231. + ebl_pid_memory_read_t *readfunc, void *arg,
  232. + bool *signal_framep __attribute__ ((unused)))
  233. +{
  234. + Dwarf_Word fp, lr, sp;
  235. +
  236. + if (!getfunc(LR_REG, 1, &lr, arg))
  237. + return false;
  238. +
  239. + if (lr == 0 || !setfunc(-1, 1, &lr, arg))
  240. + return false;
  241. +
  242. + if (!getfunc(FP_REG, 1, &fp, arg))
  243. + fp = 0;
  244. +
  245. + if (!getfunc(SP_REG, 1, &sp, arg))
  246. + sp = 0;
  247. +
  248. + Dwarf_Word newLr, newFp, newSp;
  249. +
  250. + if (!readfunc(fp + LR_OFFSET, &newLr, arg))
  251. + newLr = 0;
  252. +
  253. + if (!readfunc(fp + FP_OFFSET, &newFp, arg))
  254. + newFp = 0;
  255. +
  256. + newSp = fp + SP_OFFSET;
  257. +
  258. + // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
  259. + setfunc(LR_REG, 1, &newLr, arg);
  260. + setfunc(FP_REG, 1, &newFp, arg);
  261. + setfunc(SP_REG, 1, &newSp, arg);
  262. +
  263. + // If the fp is invalid, we might still have a valid lr.
  264. + // But if the fp is valid, then the stack should be moving in the right direction.
  265. + return fp == 0 || newSp > sp;
  266. +}