116-arm-Use-DWARF-numbering-convention-for-pseudo-regist.patch 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. From 88ac930a725b8aac8284a2738f03b843f4343dd0 Mon Sep 17 00:00:00 2001
  2. From: Victor Do Nascimento <[email protected]>
  3. Date: Thu, 17 Nov 2022 14:48:37 +0000
  4. Subject: [PATCH 116/160] arm: Use DWARF numbering convention for
  5. pseudo-register representation
  6. The patch, initially submitted to trunk in
  7. https://sourceware.org/pipermail/binutils/2022-July/122092.html ensures correct
  8. support for handling .save directives for mixed-register type lists involving
  9. the ra_auth_code pseudo-register, whereby the support first introduced in 2.39
  10. (https://sourceware.org/pipermail/binutils/2022-May/120672.html) led to the
  11. generation of unwinder code popping registers in reversed order.
  12. gas/Changelog:
  13. * config/tc-arm.c (REG_RA_AUTH_CODE): New.
  14. (parse_dot_save): Likewise.
  15. (parse_reg_list): Remove obsolete code.
  16. (reg_names): Set ra_auth_code to 143.
  17. (s_arm_unwind_save): Handle core and pseudo-register lists via
  18. parse_dot_save.
  19. (s_arm_unwind_save_mixed): Deleted.
  20. (s_arm_unwind_save_pseudo): Handle one register at a time.
  21. * testsuite/gas/arm/unwind-pacbti-m-readelf.d: Fix test.
  22. * testsuite/gas/arm/unwind-pacbti-m.d: Likewise.
  23. (cherry picked from commit 3a368c4c248f6e9f4bda3a5369befa17a4560293)
  24. ---
  25. gas/config/tc-arm.c | 159 ++++++++++--------
  26. .../gas/arm/unwind-pacbti-m-readelf.d | 4 +-
  27. gas/testsuite/gas/arm/unwind-pacbti-m.d | 2 +-
  28. 3 files changed, 95 insertions(+), 70 deletions(-)
  29. --- a/gas/config/tc-arm.c
  30. +++ b/gas/config/tc-arm.c
  31. @@ -742,6 +742,7 @@ const char * const reg_expected_msgs[] =
  32. #define REG_SP 13
  33. #define REG_LR 14
  34. #define REG_PC 15
  35. +#define REG_RA_AUTH_CODE 143
  36. /* ARM instructions take 4bytes in the object file, Thumb instructions
  37. take 2: */
  38. @@ -1943,21 +1944,6 @@ parse_reg_list (char ** strp, enum reg_l
  39. reg = arm_reg_parse (&str, rt);
  40. - /* Skip over allowed registers of alternative types in mixed-type
  41. - register lists. */
  42. - if (reg == FAIL && rt == REG_TYPE_PSEUDO
  43. - && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
  44. - {
  45. - cur_reg = reg;
  46. - continue;
  47. - }
  48. - else if (reg == FAIL && rt == REG_TYPE_RN
  49. - && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
  50. - {
  51. - cur_reg = reg;
  52. - continue;
  53. - }
  54. -
  55. if (etype == REGLIST_CLRM)
  56. {
  57. if (reg == REG_SP || reg == REG_PC)
  58. @@ -4139,7 +4125,6 @@ s_arm_unwind_fnstart (int ignored ATTRIB
  59. unwind.sp_restored = 0;
  60. }
  61. -
  62. /* Parse a handlerdata directive. Creates the exception handling table entry
  63. for the function. */
  64. @@ -4297,15 +4282,19 @@ s_arm_unwind_personality (int ignored AT
  65. /* Parse a directive saving pseudo registers. */
  66. static void
  67. -s_arm_unwind_save_pseudo (long range)
  68. +s_arm_unwind_save_pseudo (int regno)
  69. {
  70. valueT op;
  71. - if (range & (1 << 12))
  72. + switch (regno)
  73. {
  74. + case REG_RA_AUTH_CODE:
  75. /* Opcode for restoring RA_AUTH_CODE. */
  76. op = 0xb4;
  77. add_unwind_opcode (op, 1);
  78. + break;
  79. + default:
  80. + as_bad (_("Unknown register %d encountered\n"), regno);
  81. }
  82. }
  83. @@ -4375,6 +4364,80 @@ s_arm_unwind_save_core (long range)
  84. }
  85. }
  86. +/* Implement correct handling of .save lists enabling the split into
  87. +sublists where necessary, while preserving correct sublist ordering. */
  88. +
  89. +static void
  90. +parse_dot_save (char **str_p, int prev_reg)
  91. +{
  92. + long core_regs = 0;
  93. + int reg;
  94. + int in_range = 0;
  95. +
  96. + if (**str_p == ',')
  97. + *str_p += 1;
  98. + if (**str_p == '}')
  99. + {
  100. + *str_p += 1;
  101. + return;
  102. + }
  103. +
  104. + while ((reg = arm_reg_parse (str_p, REG_TYPE_RN)) != FAIL)
  105. + {
  106. + if (!in_range)
  107. + {
  108. + if (core_regs & (1 << reg))
  109. + as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
  110. + reg);
  111. + else if (reg <= prev_reg)
  112. + as_tsktsk (_("Warning: register list not in ascending order"));
  113. +
  114. + core_regs |= (1 << reg);
  115. + prev_reg = reg;
  116. + if (skip_past_char(str_p, '-') != FAIL)
  117. + in_range = 1;
  118. + else if (skip_past_comma(str_p) == FAIL)
  119. + first_error (_("bad register list"));
  120. + }
  121. + else
  122. + {
  123. + int i;
  124. + if (reg <= prev_reg)
  125. + first_error (_("bad range in register list"));
  126. + for (i = prev_reg + 1; i <= reg; i++)
  127. + {
  128. + if (core_regs & (1 << i))
  129. + as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
  130. + i);
  131. + else
  132. + core_regs |= 1 << i;
  133. + }
  134. + in_range = 0;
  135. + }
  136. + }
  137. + if (core_regs)
  138. + {
  139. + /* Higher register numbers go in higher memory addresses. When splitting a list,
  140. + right-most sublist should therefore be .saved first. Use recursion for this. */
  141. + parse_dot_save (str_p, reg);
  142. + /* We're back from recursion, so emit .save insn for sublist. */
  143. + s_arm_unwind_save_core (core_regs);
  144. + return;
  145. + }
  146. + /* Handle pseudo-regs, under assumption these are emitted singly. */
  147. + else if ((reg = arm_reg_parse (str_p, REG_TYPE_PSEUDO)) != FAIL)
  148. + {
  149. + /* Recurse for remainder of input. Note: No assumption is made regarding which
  150. + register in core register set holds pseudo-register. It's not considered in
  151. + ordering check beyond ensuring it's not sandwiched between 2 consecutive
  152. + registers. */
  153. + parse_dot_save (str_p, prev_reg + 1);
  154. + s_arm_unwind_save_pseudo (reg);
  155. + return;
  156. + }
  157. + else
  158. + as_bad (BAD_SYNTAX);
  159. +}
  160. /* Parse a directive saving FPA registers. */
  161. @@ -4716,39 +4779,13 @@ s_arm_unwind_save_mmxwcg (void)
  162. ignore_rest_of_line ();
  163. }
  164. -/* Convert range and mask_range into a sequence of s_arm_unwind_core
  165. - and s_arm_unwind_pseudo operations. We assume that mask_range will
  166. - not have consecutive bits set, or that one operation per bit is
  167. - acceptable. */
  168. -
  169. -static void
  170. -s_arm_unwind_save_mixed (long range, long mask_range)
  171. -{
  172. - while (mask_range)
  173. - {
  174. - long mask_bit = mask_range & -mask_range;
  175. - long subrange = range & (mask_bit - 1);
  176. -
  177. - if (subrange)
  178. - s_arm_unwind_save_core (subrange);
  179. -
  180. - s_arm_unwind_save_pseudo (mask_bit);
  181. - range &= ~subrange;
  182. - mask_range &= ~mask_bit;
  183. - }
  184. -
  185. - if (range)
  186. - s_arm_unwind_save_core (range);
  187. -}
  188. -
  189. /* Parse an unwind_save directive.
  190. If the argument is non-zero, this is a .vsave directive. */
  191. static void
  192. s_arm_unwind_save (int arch_v6)
  193. {
  194. - char *peek, *mask_peek;
  195. - long range, mask_range;
  196. + char *peek;
  197. struct reg_entry *reg;
  198. bool had_brace = false;
  199. @@ -4756,7 +4793,7 @@ s_arm_unwind_save (int arch_v6)
  200. as_bad (MISSING_FNSTART);
  201. /* Figure out what sort of save we have. */
  202. - peek = mask_peek = input_line_pointer;
  203. + peek = input_line_pointer;
  204. if (*peek == '{')
  205. {
  206. @@ -4788,20 +4825,13 @@ s_arm_unwind_save (int arch_v6)
  207. case REG_TYPE_PSEUDO:
  208. case REG_TYPE_RN:
  209. - mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
  210. - range = parse_reg_list (&input_line_pointer, REGLIST_RN);
  211. -
  212. - if (range == FAIL || mask_range == FAIL)
  213. - {
  214. - as_bad (_("expected register list"));
  215. - ignore_rest_of_line ();
  216. - return;
  217. - }
  218. -
  219. - demand_empty_rest_of_line ();
  220. -
  221. - s_arm_unwind_save_mixed (range, mask_range);
  222. - return;
  223. + {
  224. + if (had_brace)
  225. + input_line_pointer++;
  226. + parse_dot_save (&input_line_pointer, -1);
  227. + demand_empty_rest_of_line ();
  228. + return;
  229. + }
  230. case REG_TYPE_VFD:
  231. if (arch_v6)
  232. @@ -23993,12 +24023,8 @@ static const struct reg_entry reg_names[
  233. /* XScale accumulator registers. */
  234. REGNUM(acc,0,XSCALE), REGNUM(ACC,0,XSCALE),
  235. - /* DWARF ABI defines RA_AUTH_CODE to 143. It also reserves 134-142 for future
  236. - expansion. RA_AUTH_CODE here is given the value 143 % 134 to make it easy
  237. - for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
  238. - 134 + reg_number should the range 134 to 142 be used for more pseudo regs
  239. - in the future. This also helps fit RA_AUTH_CODE into a bitmask. */
  240. - REGDEF(ra_auth_code,12,PSEUDO),
  241. + /* AADWARF32 defines RA_AUTH_CODE to 143. */
  242. + REGDEF(ra_auth_code,143,PSEUDO),
  243. };
  244. #undef REGDEF
  245. #undef REGNUM
  246. @@ -27905,7 +27931,6 @@ create_unwind_entry (int have_data)
  247. return 0;
  248. }
  249. -
  250. /* Initialize the DWARF-2 unwind information for this procedure. */
  251. void
  252. --- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
  253. +++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
  254. @@ -10,11 +10,11 @@ Unwind section '.ARM.exidx' at offset 0x
  255. 0x0 <foo>: @0x0
  256. Compact model index: 1
  257. - 0x84 0x00 pop {r14}
  258. 0xb4 pop {ra_auth_code}
  259. 0x84 0x00 pop {r14}
  260. - 0xb4 pop {ra_auth_code}
  261. 0xa3 pop {r4, r5, r6, r7}
  262. 0xb4 pop {ra_auth_code}
  263. + 0x84 0x00 pop {r14}
  264. + 0xb4 pop {ra_auth_code}
  265. 0xa8 pop {r4, r14}
  266. 0xb0 finish
  267. --- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
  268. +++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
  269. @@ -8,4 +8,4 @@
  270. .*: file format.*
  271. Contents of section .ARM.extab:
  272. - 0000 (00840281 b40084b4 b0a8b4a3|81028400 b48400b4 a3b4a8b0) 00000000 .*
  273. + 0000 (84b40281 84b4a300 b0a8b400|8102b484 00a3b484 00b4a8b0) 00000000 .*