1 /* tc-i386-ginsn.c -- Ginsn generation for the x86-64 ISA
3 Copyright (C) 2024 Free Software Foundation, Inc.
5 This file is part of GAS.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the license, or
10 (at your option) any later version.
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
21 /* This file contains the implementation of the ginsn creation for x86-64
24 /* DWARF register number for EFLAGS. Used for pushf/popf insns. */
25 #define GINSN_DW2_REGNUM_EFLAGS 49
26 /* DWARF register number for RSI. Used as dummy value when RegIP/RegIZ. */
27 #define GINSN_DW2_REGNUM_RSI_DUMMY 4
29 /* Identify the callee-saved registers in System V AMD64 ABI. */
32 x86_scfi_callee_saved_p (unsigned int dw2reg_num
)
34 if (dw2reg_num
== 3 /* rbx. */
35 || dw2reg_num
== REG_FP
/* rbp. */
36 || dw2reg_num
== REG_SP
/* rsp. */
37 || (dw2reg_num
>= 12 && dw2reg_num
<= 15) /* r12 - r15. */)
43 /* Check whether an instruction prefix which affects operation size
44 accompanies. For insns in the legacy space, setting REX.W takes precedence
45 over the operand-size prefix (66H) when both are used.
47 The current users of this API are in the handlers for PUSH, POP or other
48 instructions which affect the stack pointer implicitly: the operation size
49 (16, 32, or 64 bits) determines the amount by which the stack pointer is
50 incremented / decremented (2, 4 or 8). */
53 ginsn_opsize_prefix_p (void)
55 return (!(i
.prefix
[REX_PREFIX
] & REX_W
) && i
.prefix
[DATA_PREFIX
]);
58 /* Get the DWARF register number for the given register entry.
59 For specific byte/word/dword register accesses like al, cl, ah, ch, r8d,
60 r20w etc., we need to identify the DWARF register number for the
61 corresponding 8-byte GPR.
63 This function is a hack - it relies on relative ordering of reg entries in
64 the i386_regtab. FIXME - it will be good to allow a more direct way to get
68 ginsn_dw2_regnum (const reg_entry
*ireg
)
70 const reg_entry
*temp
= ireg
;
71 unsigned int dwarf_reg
= Dw2Inval
, idx
= 0;
73 /* ginsn creation is available for AMD64 abi only ATM. Other flag_code
75 gas_assert (ireg
&& flag_code
== CODE_64BIT
);
77 /* Watch out for RegIP, RegIZ. These are expected to appear only with
78 base/index addressing modes. Although creating inaccurate data
79 dependencies, using a dummy value (lets say volatile register rsi) will
80 not hurt SCFI. TBD_GINSN_GEN_NOT_SCFI. */
81 if (ireg
->reg_num
== RegIP
|| ireg
->reg_num
== RegIZ
)
82 return GINSN_DW2_REGNUM_RSI_DUMMY
;
84 dwarf_reg
= ireg
->dw2_regnum
[object_64bit
];
86 if (dwarf_reg
== Dw2Inval
)
88 if (ireg
<= &i386_regtab
[3])
89 /* For al, cl, dl, bl, bump over to axl, cxl, dxl, bxl respectively by
92 else if (ireg
<= &i386_regtab
[7])
93 /* For ah, ch, dh, bh, bump over to axl, cxl, dxl, bxl respectively by
98 /* The code relies on the relative ordering of the reg entries in
99 i386_regtab. There are 32 register entries between axl-r31b,
100 ax-r31w etc. The assertions here ensures the code does not
101 recurse indefinitely. */
102 gas_assert ((temp
- &i386_regtab
[0]) >= 0);
103 idx
= temp
- &i386_regtab
[0];
104 gas_assert (idx
+ 32 < i386_regtab_size
- 1);
109 dwarf_reg
= ginsn_dw2_regnum (temp
);
112 /* Sanity check - failure may indicate state corruption, bad ginsn or
113 perhaps the i386-reg table and the current function got out of sync. */
114 gas_assert (dwarf_reg
< Dw2Inval
);
120 x86_ginsn_addsub_reg_mem (const symbolS
*insn_end_sym
)
122 unsigned int dw2_regnum
;
123 unsigned int src1_dw2_regnum
;
124 ginsnS
*ginsn
= NULL
;
125 ginsnS
* (*ginsn_func
) (const symbolS
*, bool,
126 enum ginsn_src_type
, unsigned int, offsetT
,
127 enum ginsn_src_type
, unsigned int, offsetT
,
128 enum ginsn_dst_type
, unsigned int, offsetT
);
129 uint16_t opcode
= i
.tm
.base_opcode
;
131 gas_assert (i
.tm
.opcode_space
== SPACE_BASE
132 && (opcode
== 0x1 || opcode
== 0x29));
133 ginsn_func
= (opcode
== 0x1) ? ginsn_new_add
: ginsn_new_sub
;
135 /* op %reg, symbol or even other cases where destination involves indirect
136 access are unnecessary for SCFI correctness. TBD_GINSN_GEN_NOT_SCFI. */
140 /* Skip detection of 8/16/32-bit op size; 'add/sub reg, reg/mem' ops always
141 make the dest reg untraceable for SCFI. */
143 /* op reg, reg/mem. */
144 src1_dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
145 /* Of interest only when second opnd is not memory. */
146 if (i
.reg_operands
== 2)
148 dw2_regnum
= ginsn_dw2_regnum (i
.op
[1].regs
);
149 ginsn
= ginsn_func (insn_end_sym
, true,
150 GINSN_SRC_REG
, src1_dw2_regnum
, 0,
151 GINSN_SRC_REG
, dw2_regnum
, 0,
152 GINSN_DST_REG
, dw2_regnum
, 0);
153 ginsn_set_where (ginsn
);
160 x86_ginsn_addsub_mem_reg (const symbolS
*insn_end_sym
)
162 unsigned int dw2_regnum
;
163 unsigned int src1_dw2_regnum
;
164 const reg_entry
*mem_reg
;
166 ginsnS
*ginsn
= NULL
;
167 ginsnS
* (*ginsn_func
) (const symbolS
*, bool,
168 enum ginsn_src_type
, unsigned int, offsetT
,
169 enum ginsn_src_type
, unsigned int, offsetT
,
170 enum ginsn_dst_type
, unsigned int, offsetT
);
171 uint16_t opcode
= i
.tm
.base_opcode
;
173 gas_assert (i
.tm
.opcode_space
== SPACE_BASE
174 && (opcode
== 0x3 || opcode
== 0x2b));
175 ginsn_func
= (opcode
== 0x3) ? ginsn_new_add
: ginsn_new_sub
;
177 /* op symbol, %reg. */
178 if (i
.mem_operands
&& !i
.base_reg
&& !i
.index_reg
)
181 /* Skip detection of 8/16/32-bit op size; 'add/sub reg/mem, reg' ops always
182 make the dest reg untraceable for SCFI. */
184 /* op reg/mem, %reg. */
185 dw2_regnum
= ginsn_dw2_regnum (i
.op
[1].regs
);
187 if (i
.reg_operands
== 2)
189 src1_dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
190 ginsn
= ginsn_func (insn_end_sym
, true,
191 GINSN_SRC_REG
, src1_dw2_regnum
, 0,
192 GINSN_SRC_REG
, dw2_regnum
, 0,
193 GINSN_DST_REG
, dw2_regnum
, 0);
194 ginsn_set_where (ginsn
);
196 else if (i
.mem_operands
)
198 mem_reg
= (i
.base_reg
) ? i
.base_reg
: i
.index_reg
;
199 src1_dw2_regnum
= ginsn_dw2_regnum (mem_reg
);
200 if (i
.disp_operands
== 1)
201 gdisp
= i
.op
[0].disps
->X_add_number
;
202 ginsn
= ginsn_func (insn_end_sym
, true,
203 GINSN_SRC_INDIRECT
, src1_dw2_regnum
, gdisp
,
204 GINSN_SRC_REG
, dw2_regnum
, 0,
205 GINSN_DST_REG
, dw2_regnum
, 0);
206 ginsn_set_where (ginsn
);
213 x86_ginsn_alu_imm (const symbolS
*insn_end_sym
)
216 unsigned int dw2_regnum
;
217 ginsnS
*ginsn
= NULL
;
218 enum ginsn_src_type src_type
= GINSN_SRC_REG
;
219 enum ginsn_dst_type dst_type
= GINSN_DST_REG
;
221 ginsnS
* (*ginsn_func
) (const symbolS
*, bool,
222 enum ginsn_src_type
, unsigned int, offsetT
,
223 enum ginsn_src_type
, unsigned int, offsetT
,
224 enum ginsn_dst_type
, unsigned int, offsetT
);
226 /* FIXME - create ginsn where dest is REG_SP / REG_FP only ? */
227 /* Map for insn.tm.extension_opcode
233 /* add/sub/and imm, %reg only at this time for SCFI.
234 Although all three ('and', 'or' , 'xor') make the destination reg
235 untraceable, 'and' op is handled but not 'or' / 'xor' because we will look
236 into supporting the DRAP pattern at some point. Other opcodes ('adc',
237 'sbb' and 'cmp') are not generated here either. The ginsn representation
238 does not have support for the latter three opcodes; GINSN_TYPE_OTHER may
239 be added for these after x86_ginsn_unhandled () invocation if the
240 destination register is REG_SP or REG_FP. */
241 if (i
.tm
.extension_opcode
== 5)
242 ginsn_func
= ginsn_new_sub
;
243 else if (i
.tm
.extension_opcode
== 4)
244 ginsn_func
= ginsn_new_and
;
245 else if (i
.tm
.extension_opcode
== 0)
246 ginsn_func
= ginsn_new_add
;
250 /* TBD_GINSN_REPRESENTATION_LIMIT: There is no representation for when a
251 symbol is used as an operand, like so:
252 addq $simd_cmp_op+8, %rdx
253 Skip generating any ginsn for this. */
254 if (i
.imm_operands
== 1
255 && i
.op
[0].imms
->X_op
!= O_constant
)
260 These are not of interest for SCFI. Also, TBD_GINSN_GEN_NOT_SCFI. */
261 if (i
.mem_operands
== 1)
264 /* 8/16/32-bit op size makes the destination reg untraceable for SCFI.
265 Deal with this via the x86_ginsn_unhandled () code path. */
266 if (i
.suffix
!= QWORD_MNEM_SUFFIX
)
269 gas_assert (i
.imm_operands
== 1);
270 src_imm
= i
.op
[0].imms
->X_add_number
;
271 /* The second operand may be a register or indirect access. For SCFI, only
272 the case when the second opnd is a register is interesting. Revisit this
273 if generating ginsns for a different gen mode TBD_GINSN_GEN_NOT_SCFI. */
274 if (i
.reg_operands
== 1)
276 dw2_regnum
= ginsn_dw2_regnum (i
.op
[1].regs
);
277 /* For ginsn, keep the imm as second src operand. */
278 ginsn
= ginsn_func (insn_end_sym
, true,
279 src_type
, dw2_regnum
, 0,
280 GINSN_SRC_IMM
, 0, src_imm
,
281 dst_type
, dw2_regnum
, 0);
283 ginsn_set_where (ginsn
);
289 /* Create ginsn(s) for MOV operations.
291 The generated ginsns corresponding to mov with indirect access to memory
292 (src or dest) suffer with loss of information: when both index and base
293 registers are at play, only base register gets conveyed in ginsn. Note
294 this TBD_GINSN_GEN_NOT_SCFI. */
297 x86_ginsn_move (const symbolS
*insn_end_sym
)
299 ginsnS
*ginsn
= NULL
;
300 unsigned int dst_reg
;
301 unsigned int src_reg
;
302 offsetT src_disp
= 0;
303 offsetT dst_disp
= 0;
304 const reg_entry
*dst
= NULL
;
305 const reg_entry
*src
= NULL
;
306 uint16_t opcode
= i
.tm
.base_opcode
;
307 enum ginsn_src_type src_type
= GINSN_SRC_REG
;
308 enum ginsn_dst_type dst_type
= GINSN_DST_REG
;
310 /* mov %reg, symbol or mov symbol, %reg.
311 Not of interest for SCFI. Also, TBD_GINSN_GEN_NOT_SCFI. */
312 if (i
.mem_operands
== 1 && !i
.base_reg
&& !i
.index_reg
)
315 /* 8/16/32-bit op size makes the destination reg untraceable for SCFI.
316 Handle mov reg, reg only. mov to or from a memory operand will make
317 dest reg, when present, untraceable, irrespective of the op size. */
318 if (i
.reg_operands
== 2 && i
.suffix
!= QWORD_MNEM_SUFFIX
)
321 gas_assert (i
.tm
.opcode_space
== SPACE_BASE
);
322 if (opcode
== 0x8b || opcode
== 0x8a)
324 /* mov disp(%reg), %reg. */
327 src
= (i
.base_reg
) ? i
.base_reg
: i
.index_reg
;
328 if (i
.disp_operands
== 1)
329 src_disp
= i
.op
[0].disps
->X_add_number
;
330 src_type
= GINSN_SRC_INDIRECT
;
337 else if (opcode
== 0x89 || opcode
== 0x88)
339 /* mov %reg, disp(%reg). */
343 dst
= (i
.base_reg
) ? i
.base_reg
: i
.index_reg
;
344 if (i
.disp_operands
== 1)
345 dst_disp
= i
.op
[1].disps
->X_add_number
;
346 dst_type
= GINSN_DST_INDIRECT
;
352 src_reg
= ginsn_dw2_regnum (src
);
353 dst_reg
= ginsn_dw2_regnum (dst
);
355 ginsn
= ginsn_new_mov (insn_end_sym
, true,
356 src_type
, src_reg
, src_disp
,
357 dst_type
, dst_reg
, dst_disp
);
358 ginsn_set_where (ginsn
);
363 /* Generate appropriate ginsn for lea.
365 Unhandled sub-cases (marked with TBD_GINSN_GEN_NOT_SCFI) also suffer with
366 some loss of information in the final ginsn chosen eventually (type
367 GINSN_TYPE_OTHER). But this is fine for now for GINSN_GEN_SCFI generation
371 x86_ginsn_lea (const symbolS
*insn_end_sym
)
373 offsetT src_disp
= 0;
374 ginsnS
*ginsn
= NULL
;
375 unsigned int src1_reg
;
376 const reg_entry
*src1
;
378 unsigned int dst_reg
;
381 if ((!i
.base_reg
) != (!i
.index_reg
|| i
.index_reg
->reg_num
== RegIZ
))
383 /* lea disp(%base), %dst or lea disp(,%index,imm), %dst.
384 Either index_reg or base_reg exists, but not both. Further, as per
385 above, the case when just %index exists but is equal to RegIZ is
386 excluded. If not excluded, a GINSN_TYPE_MOV of %rsi
387 (GINSN_DW2_REGNUM_RSI_DUMMY) to %dst will be generated by this block.
388 Such a mov ginsn is imprecise; so, exclude now and generate
389 GINSN_TYPE_OTHER instead later via the x86_ginsn_unhandled ().
390 Excluding other cases is required due to
391 TBD_GINSN_REPRESENTATION_LIMIT. */
393 index_scale
= i
.log2_scale_factor
;
394 index_regiz_p
= i
.index_reg
&& i
.index_reg
->reg_num
== RegIZ
;
395 src1
= i
.base_reg
? i
.base_reg
: i
.index_reg
;
396 src1_reg
= ginsn_dw2_regnum (src1
);
397 dst_reg
= ginsn_dw2_regnum (i
.op
[1].regs
);
398 /* It makes sense to represent a scale factor of 1 precisely here
399 (i.e., not using GINSN_TYPE_OTHER, but rather similar to the
400 base-without-index case). A non-zero scale factor is still OK if
401 the index reg is zero reg.
402 However, skip from here the case when disp has a symbol instead.
403 TBD_GINSN_REPRESENTATION_LIMIT. */
404 if ((!index_scale
|| index_regiz_p
)
405 && (!i
.disp_operands
|| i
.op
[0].disps
->X_op
== O_constant
))
408 src_disp
= i
.op
[0].disps
->X_add_number
;
411 /* Generate an ADD ginsn. */
412 ginsn
= ginsn_new_add (insn_end_sym
, true,
413 GINSN_SRC_REG
, src1_reg
, 0,
414 GINSN_SRC_IMM
, 0, src_disp
,
415 GINSN_DST_REG
, dst_reg
, 0);
417 /* Generate a MOV ginsn. */
418 ginsn
= ginsn_new_mov (insn_end_sym
, true,
419 GINSN_SRC_REG
, src1_reg
, 0,
420 GINSN_DST_REG
, dst_reg
, 0);
422 ginsn_set_where (ginsn
);
425 /* Skip handling other cases here,
426 - when (i.index_reg && i.base_reg) is true,
427 e.g., lea disp(%base,%index,imm), %dst
428 We do not have a ginsn representation for multiply.
429 - or, when (!i.index_reg && !i.base_reg) is true,
430 e.g., lea symbol, %dst
431 Not a frequent pattern. If %dst is a register of interest, the user is
432 likely to use a MOV op anyway.
433 Deal with these via the x86_ginsn_unhandled () code path to generate
434 GINSN_TYPE_OTHER when necessary. TBD_GINSN_GEN_NOT_SCFI. */
440 x86_ginsn_jump (const symbolS
*insn_end_sym
, bool cond_p
)
442 ginsnS
*ginsn
= NULL
;
443 const symbolS
*src_symbol
;
444 ginsnS
* (*ginsn_func
) (const symbolS
*sym
, bool real_p
,
445 enum ginsn_src_type src_type
, unsigned int src_reg
,
446 const symbolS
*src_ginsn_sym
);
448 gas_assert (i
.disp_operands
== 1);
450 ginsn_func
= cond_p
? ginsn_new_jump_cond
: ginsn_new_jump
;
451 if (i
.op
[0].disps
->X_op
== O_symbol
&& !i
.op
[0].disps
->X_add_number
)
453 src_symbol
= i
.op
[0].disps
->X_add_symbol
;
454 ginsn
= ginsn_func (insn_end_sym
, true,
455 GINSN_SRC_SYMBOL
, 0, src_symbol
);
457 ginsn_set_where (ginsn
);
461 /* A non-zero addend in jump/JCC target makes control-flow tracking
462 difficult. Skip SCFI for now. */
463 as_bad (_("SCFI: `%s' insn with non-zero addend to sym not supported"),
464 cond_p
? "JCC" : "jmp");
472 x86_ginsn_indirect_branch (const symbolS
*insn_end_sym
)
474 ginsnS
*ginsn
= NULL
;
475 const reg_entry
*mem_reg
;
476 unsigned int dw2_regnum
;
478 ginsnS
* (*ginsn_func
) (const symbolS
*sym
, bool real_p
,
479 enum ginsn_src_type src_type
, unsigned int src_reg
,
480 const symbolS
*src_ginsn_sym
);
482 /* Other cases are not expected. */
483 gas_assert (i
.tm
.extension_opcode
== 4 || i
.tm
.extension_opcode
== 2);
485 if (i
.tm
.extension_opcode
== 4)
486 /* 0xFF /4 (jmp r/m). */
487 ginsn_func
= ginsn_new_jump
;
488 else if (i
.tm
.extension_opcode
== 2)
489 /* 0xFF /2 (call r/m). */
490 ginsn_func
= ginsn_new_call
;
494 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
495 ginsn
= ginsn_func (insn_end_sym
, true,
496 GINSN_SRC_REG
, dw2_regnum
, NULL
);
497 ginsn_set_where (ginsn
);
499 else if (i
.mem_operands
)
501 /* Handle jump/call near, absolute indirect, address.
502 E.g., jmp/call *imm(%rN), jmp/call *sym(,%rN,imm)
503 or jmp/call *sym(%rN) etc. */
504 mem_reg
= i
.base_reg
? i
.base_reg
: i
.index_reg
;
505 /* Generate a ginsn, even if it is with TBD_GINSN_INFO_LOSS. Otherwise,
506 the user gets the impression of missing functionality due to this
507 being a COFI and alerted for via the x86_ginsn_unhandled () workflow
508 as unhandled operation (which can be misleading for users).
510 Indirect branches make the code block ineligible for SCFI; Hence, an
511 approximate ginsn will not affect SCFI correctness:
512 - Use dummy register if no base or index
513 - Skip symbol information, if any.
514 Note this case of TBD_GINSN_GEN_NOT_SCFI. */
515 dw2_regnum
= (mem_reg
516 ? ginsn_dw2_regnum (mem_reg
)
517 : GINSN_DW2_REGNUM_RSI_DUMMY
);
518 ginsn
= ginsn_func (insn_end_sym
, true,
519 GINSN_SRC_REG
, dw2_regnum
, NULL
);
520 ginsn_set_where (ginsn
);
527 x86_ginsn_enter (const symbolS
*insn_end_sym
)
529 ginsnS
*ginsn
= NULL
;
530 ginsnS
*ginsn_next
= NULL
;
531 ginsnS
*ginsn_last
= NULL
;
532 /* In 64-bit mode, the default stack update size is 8 bytes. */
533 int stack_opnd_size
= 8;
535 gas_assert (i
.imm_operands
== 2);
537 /* For non-zero size operands, bail out as untraceable for SCFI. */
538 if (i
.op
[0].imms
->X_op
!= O_constant
|| i
.op
[0].imms
->X_add_symbol
!= 0
539 || i
.op
[1].imms
->X_op
!= O_constant
|| i
.op
[1].imms
->X_add_symbol
!= 0)
541 as_bad ("SCFI: enter insn with non-zero operand not supported");
545 /* Check if this is a 16-bit op. */
546 if (ginsn_opsize_prefix_p ())
549 /* If the nesting level is 0, the processor pushes the frame pointer from
550 the BP/EBP/RBP register onto the stack, copies the current stack
551 pointer from the SP/ESP/RSP register into the BP/EBP/RBP register, and
552 loads the SP/ESP/RSP register with the current stack-pointer value
553 minus the value in the size operand. */
554 ginsn
= ginsn_new_sub (insn_end_sym
, false,
555 GINSN_SRC_REG
, REG_SP
, 0,
556 GINSN_SRC_IMM
, 0, stack_opnd_size
,
557 GINSN_DST_REG
, REG_SP
, 0);
558 ginsn_set_where (ginsn
);
559 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
560 GINSN_SRC_REG
, REG_FP
,
561 GINSN_DST_INDIRECT
, REG_SP
, 0);
562 ginsn_set_where (ginsn_next
);
563 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
564 ginsn_last
= ginsn_new_mov (insn_end_sym
, false,
565 GINSN_SRC_REG
, REG_SP
, 0,
566 GINSN_DST_REG
, REG_FP
, 0);
567 ginsn_set_where (ginsn_last
);
568 gas_assert (!ginsn_link_next (ginsn_next
, ginsn_last
));
574 x86_ginsn_leave (const symbolS
*insn_end_sym
)
576 ginsnS
*ginsn
= NULL
;
577 ginsnS
*ginsn_next
= NULL
;
578 ginsnS
*ginsn_last
= NULL
;
579 /* In 64-bit mode, the default stack update size is 8 bytes. */
580 int stack_opnd_size
= 8;
582 /* Check if this is a 16-bit op. */
583 if (ginsn_opsize_prefix_p ())
586 /* The 'leave' instruction copies the contents of the RBP register
587 into the RSP register to release all stack space allocated to the
589 ginsn
= ginsn_new_mov (insn_end_sym
, false,
590 GINSN_SRC_REG
, REG_FP
, 0,
591 GINSN_DST_REG
, REG_SP
, 0);
592 ginsn_set_where (ginsn
);
593 /* Then it restores the old value of the RBP register from the stack. */
594 ginsn_next
= ginsn_new_load (insn_end_sym
, false,
595 GINSN_SRC_INDIRECT
, REG_SP
, 0,
596 GINSN_DST_REG
, REG_FP
);
597 ginsn_set_where (ginsn_next
);
598 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
599 ginsn_last
= ginsn_new_add (insn_end_sym
, false,
600 GINSN_SRC_REG
, REG_SP
, 0,
601 GINSN_SRC_IMM
, 0, stack_opnd_size
,
602 GINSN_DST_REG
, REG_SP
, 0);
603 ginsn_set_where (ginsn_next
);
604 gas_assert (!ginsn_link_next (ginsn_next
, ginsn_last
));
609 /* Check if an instruction is whitelisted.
611 Some instructions may appear with REG_SP or REG_FP as destination, because
612 which they are deemed 'interesting' for SCFI. Whitelist them here if they
613 do not affect SCFI correctness. */
616 x86_ginsn_safe_to_skip_p (void)
619 uint16_t opcode
= i
.tm
.base_opcode
;
626 if (i
.tm
.opcode_space
!= SPACE_BASE
)
628 /* cmp imm, reg/rem. */
629 if (i
.tm
.extension_opcode
== 7)
637 if (i
.tm
.opcode_space
!= SPACE_BASE
)
639 /* cmp imm/reg/mem, reg/rem. */
647 /* test imm/reg/mem, reg/mem. */
648 if (i
.tm
.opcode_space
!= SPACE_BASE
)
660 #define X86_GINSN_UNHANDLED_NONE 0
661 #define X86_GINSN_UNHANDLED_DEST_REG 1
662 #define X86_GINSN_UNHANDLED_CFG 2
663 #define X86_GINSN_UNHANDLED_STACKOP 3
664 #define X86_GINSN_UNHANDLED_UNEXPECTED 4
666 /* Check the input insn for its impact on the correctness of the synthesized
667 CFI. Returns an error code to the caller. */
670 x86_ginsn_unhandled (void)
672 int err
= X86_GINSN_UNHANDLED_NONE
;
673 const reg_entry
*reg_op
;
674 unsigned int dw2_regnum
;
676 /* Keep an eye out for instructions affecting control flow. */
677 if (i
.tm
.opcode_modifier
.jump
)
678 err
= X86_GINSN_UNHANDLED_CFG
;
679 /* Also, for any instructions involving an implicit update to the stack
681 else if (i
.tm
.opcode_modifier
.operandconstraint
== IMPLICIT_STACK_OP
)
682 err
= X86_GINSN_UNHANDLED_STACKOP
;
683 /* Finally, also check if the missed instructions are affecting REG_SP or
684 REG_FP. The destination operand is the last at all stages of assembly
685 (due to following AT&T syntax layout in the internal representation). In
686 case of Intel syntax input, this still remains true as swap_operands ()
688 PS: These checks do not involve index / base reg, as indirect memory
689 accesses via REG_SP or REG_FP do not affect SCFI correctness.
690 (Also note these instructions are candidates for other ginsn generation
691 modes in future. TBD_GINSN_GEN_NOT_SCFI.) */
692 else if (i
.operands
&& i
.reg_operands
693 && !(i
.flags
[i
.operands
- 1] & Operand_Mem
))
695 reg_op
= i
.op
[i
.operands
- 1].regs
;
698 dw2_regnum
= ginsn_dw2_regnum (reg_op
);
699 if (dw2_regnum
== REG_SP
|| dw2_regnum
== REG_FP
)
700 err
= X86_GINSN_UNHANDLED_DEST_REG
;
703 /* Something unexpected. Indicate to caller. */
704 err
= X86_GINSN_UNHANDLED_UNEXPECTED
;
710 /* Generate one or more generic GAS instructions, a.k.a, ginsns for the current
713 Returns the head of linked list of ginsn(s) added, if success; Returns NULL
716 The input ginsn_gen_mode GMODE determines the set of minimal necessary
717 ginsns necessary for correctness of any passes applicable for that mode.
718 For supporting the GINSN_GEN_SCFI generation mode, following is the list of
719 machine instructions that must be translated into the corresponding ginsns
720 to ensure correctness of SCFI:
721 - All instructions affecting the two registers that could potentially
722 be used as the base register for CFA tracking. For SCFI, the base
723 register for CFA tracking is limited to REG_SP and REG_FP only for
725 - All change of flow instructions: conditional and unconditional branches,
726 call and return from functions.
727 - All instructions that can potentially be a register save / restore
729 - All instructions that perform stack manipulation implicitly: the CALL,
730 RET, PUSH, POP, ENTER, and LEAVE instructions.
732 The function currently supports GINSN_GEN_SCFI ginsn generation mode only.
733 To support other generation modes will require work on this target-specific
734 process of creation of ginsns:
735 - Some of such places are tagged with TBD_GINSN_GEN_NOT_SCFI to serve as
736 possible starting points.
737 - Also note that ginsn representation may need enhancements. Specifically,
738 note some TBD_GINSN_INFO_LOSS and TBD_GINSN_REPRESENTATION_LIMIT markers.
742 x86_ginsn_new (const symbolS
*insn_end_sym
, enum ginsn_gen_mode gmode
)
746 unsigned int dw2_regnum
;
747 const reg_entry
*mem_reg
;
748 ginsnS
*ginsn
= NULL
;
749 ginsnS
*ginsn_next
= NULL
;
750 /* In 64-bit mode, the default stack update size is 8 bytes. */
751 int stack_opnd_size
= 8;
753 /* Currently supports generation of selected ginsns, sufficient for
754 the use-case of SCFI only. */
755 if (gmode
!= GINSN_GEN_SCFI
)
758 opcode
= i
.tm
.base_opcode
;
760 /* Until it is clear how to handle APX NDD and other new opcodes, disallow
762 if (is_apx_rex2_encoding ()
763 || (i
.tm
.opcode_modifier
.evex
&& is_apx_evex_encoding ()))
765 as_bad (_("SCFI: unsupported APX op %#x may cause incorrect CFI"),
773 /* Add opcodes 0x0/0x2 and sub opcodes 0x28/0x2a (with opcode_space
774 SPACE_BASE) are 8-bit ops. While they are relevant for SCFI
775 correctness, skip handling them here and use the x86_ginsn_unhandled
776 code path to generate GINSN_TYPE_OTHER when necessary. */
778 case 0x1: /* add reg, reg/mem. */
779 case 0x29: /* sub reg, reg/mem. */
780 if (i
.tm
.opcode_space
!= SPACE_BASE
)
782 ginsn
= x86_ginsn_addsub_reg_mem (insn_end_sym
);
785 case 0x3: /* add reg/mem, reg. */
786 case 0x2b: /* sub reg/mem, reg. */
787 if (i
.tm
.opcode_space
!= SPACE_BASE
)
789 ginsn
= x86_ginsn_addsub_mem_reg (insn_end_sym
);
792 case 0xa0: /* push fs. */
793 case 0xa8: /* push gs. */
794 /* push fs / push gs have opcode_space == SPACE_0F. */
795 if (i
.tm
.opcode_space
!= SPACE_0F
)
797 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
798 /* Check if operation size is 16-bit. */
799 if (ginsn_opsize_prefix_p ())
801 ginsn
= ginsn_new_sub (insn_end_sym
, false,
802 GINSN_SRC_REG
, REG_SP
, 0,
803 GINSN_SRC_IMM
, 0, stack_opnd_size
,
804 GINSN_DST_REG
, REG_SP
, 0);
805 ginsn_set_where (ginsn
);
806 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
807 GINSN_SRC_REG
, dw2_regnum
,
808 GINSN_DST_INDIRECT
, REG_SP
, 0);
809 ginsn_set_where (ginsn_next
);
810 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
813 case 0xa1: /* pop fs. */
814 case 0xa9: /* pop gs. */
815 /* pop fs / pop gs have opcode_space == SPACE_0F. */
816 if (i
.tm
.opcode_space
!= SPACE_0F
)
818 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
819 /* Check if operation size is 16-bit. */
820 if (ginsn_opsize_prefix_p ())
822 ginsn
= ginsn_new_load (insn_end_sym
, false,
823 GINSN_SRC_INDIRECT
, REG_SP
, 0,
824 GINSN_DST_REG
, dw2_regnum
);
825 ginsn_set_where (ginsn
);
826 ginsn_next
= ginsn_new_add (insn_end_sym
, false,
827 GINSN_SRC_REG
, REG_SP
, 0,
828 GINSN_SRC_IMM
, 0, stack_opnd_size
,
829 GINSN_DST_REG
, REG_SP
, 0);
830 ginsn_set_where (ginsn_next
);
831 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
835 if (i
.tm
.opcode_space
!= SPACE_BASE
)
838 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
839 /* Check if operation size is 16-bit. */
840 if (ginsn_opsize_prefix_p ())
842 ginsn
= ginsn_new_sub (insn_end_sym
, false,
843 GINSN_SRC_REG
, REG_SP
, 0,
844 GINSN_SRC_IMM
, 0, stack_opnd_size
,
845 GINSN_DST_REG
, REG_SP
, 0);
846 ginsn_set_where (ginsn
);
847 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
848 GINSN_SRC_REG
, dw2_regnum
,
849 GINSN_DST_INDIRECT
, REG_SP
, 0);
850 ginsn_set_where (ginsn_next
);
851 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
855 if (i
.tm
.opcode_space
!= SPACE_BASE
)
858 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
859 ginsn
= ginsn_new_load (insn_end_sym
, false,
860 GINSN_SRC_INDIRECT
, REG_SP
, 0,
861 GINSN_DST_REG
, dw2_regnum
);
862 ginsn_set_where (ginsn
);
863 /* Check if operation size is 16-bit. */
864 if (ginsn_opsize_prefix_p ())
866 ginsn_next
= ginsn_new_add (insn_end_sym
, false,
867 GINSN_SRC_REG
, REG_SP
, 0,
868 GINSN_SRC_IMM
, 0, stack_opnd_size
,
869 GINSN_DST_REG
, REG_SP
, 0);
870 ginsn_set_where (ginsn_next
);
871 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
874 case 0x6a: /* push imm8. */
875 case 0x68: /* push imm16/imm32. */
876 if (i
.tm
.opcode_space
!= SPACE_BASE
)
878 /* Check if operation size is 16-bit. */
879 if (ginsn_opsize_prefix_p ())
881 /* Skip getting the value of imm from machine instruction
882 because this is not important for SCFI. */
883 ginsn
= ginsn_new_sub (insn_end_sym
, false,
884 GINSN_SRC_REG
, REG_SP
, 0,
885 GINSN_SRC_IMM
, 0, stack_opnd_size
,
886 GINSN_DST_REG
, REG_SP
, 0);
887 ginsn_set_where (ginsn
);
888 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
890 GINSN_DST_INDIRECT
, REG_SP
, 0);
891 ginsn_set_where (ginsn_next
);
892 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
895 /* PS: Opcodes 0x80 ... 0x8f with opcode_space SPACE_0F are present
896 only after relaxation. They do not need to be handled for ginsn
899 if (i
.tm
.opcode_space
!= SPACE_BASE
)
901 ginsn
= x86_ginsn_jump (insn_end_sym
, true);
907 if (i
.tm
.opcode_space
!= SPACE_BASE
)
909 ginsn
= x86_ginsn_alu_imm (insn_end_sym
);
912 case 0x8a: /* mov r/m8, r8. */
913 case 0x8b: /* mov r/m(16/32/64), r(16/32/64). */
914 case 0x88: /* mov r8, r/m8. */
915 case 0x89: /* mov r(16/32/64), r/m(16/32/64). */
916 if (i
.tm
.opcode_space
!= SPACE_BASE
)
918 ginsn
= x86_ginsn_move (insn_end_sym
);
922 if (i
.tm
.opcode_space
!= SPACE_BASE
)
924 /* lea disp(%base,%index,imm), %dst. */
925 ginsn
= x86_ginsn_lea (insn_end_sym
);
929 if (i
.tm
.opcode_space
!= SPACE_BASE
)
931 /* pop to reg/mem. */
934 mem_reg
= (i
.base_reg
) ? i
.base_reg
: i
.index_reg
;
935 /* Use dummy register if no base or index. Unlike other opcodes,
936 ginsns must be generated as this affect stack pointer. */
937 dw2_regnum
= (mem_reg
938 ? ginsn_dw2_regnum (mem_reg
)
939 : GINSN_DW2_REGNUM_RSI_DUMMY
);
942 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
943 ginsn
= ginsn_new_load (insn_end_sym
, false,
944 GINSN_SRC_INDIRECT
, REG_SP
, 0,
945 GINSN_DST_INDIRECT
, dw2_regnum
);
946 ginsn_set_where (ginsn
);
947 /* Check if operation size is 16-bit. */
948 if (ginsn_opsize_prefix_p ())
950 ginsn_next
= ginsn_new_add (insn_end_sym
, false,
951 GINSN_SRC_REG
, REG_SP
, 0,
952 GINSN_SRC_IMM
, 0, stack_opnd_size
,
953 GINSN_DST_REG
, REG_SP
, 0);
954 ginsn_set_where (ginsn_next
);
955 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
959 if (i
.tm
.opcode_space
!= SPACE_BASE
)
961 /* pushf / pushfq. */
962 /* Check if operation size is 16-bit. */
963 if (ginsn_opsize_prefix_p ())
965 ginsn
= ginsn_new_sub (insn_end_sym
, false,
966 GINSN_SRC_REG
, REG_SP
, 0,
967 GINSN_SRC_IMM
, 0, stack_opnd_size
,
968 GINSN_DST_REG
, REG_SP
, 0);
969 ginsn_set_where (ginsn
);
970 /* FIXME - hardcode the actual DWARF reg number value. As for SCFI
971 correctness, although this behaves simply a placeholder value; its
972 just clearer if the value is correct. */
973 dw2_regnum
= GINSN_DW2_REGNUM_EFLAGS
;
974 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
975 GINSN_SRC_REG
, dw2_regnum
,
976 GINSN_DST_INDIRECT
, REG_SP
, 0);
977 ginsn_set_where (ginsn_next
);
978 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
982 if (i
.tm
.opcode_space
!= SPACE_BASE
)
985 /* Check if operation size is 16-bit. */
986 if (ginsn_opsize_prefix_p ())
988 /* FIXME - hardcode the actual DWARF reg number value. As for SCFI
989 correctness, although this behaves simply a placeholder value; its
990 just clearer if the value is correct. */
991 dw2_regnum
= GINSN_DW2_REGNUM_EFLAGS
;
992 ginsn
= ginsn_new_load (insn_end_sym
, false,
993 GINSN_SRC_INDIRECT
, REG_SP
, 0,
994 GINSN_DST_REG
, dw2_regnum
);
995 ginsn_set_where (ginsn
);
996 ginsn_next
= ginsn_new_add (insn_end_sym
, false,
997 GINSN_SRC_REG
, REG_SP
, 0,
998 GINSN_SRC_IMM
, 0, stack_opnd_size
,
999 GINSN_DST_REG
, REG_SP
, 0);
1000 ginsn_set_where (ginsn_next
);
1001 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
1005 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1007 /* push from reg/mem. */
1008 if (i
.tm
.extension_opcode
== 6)
1010 /* Check if operation size is 16-bit. */
1011 if (ginsn_opsize_prefix_p ())
1012 stack_opnd_size
= 2;
1013 ginsn
= ginsn_new_sub (insn_end_sym
, false,
1014 GINSN_SRC_REG
, REG_SP
, 0,
1015 GINSN_SRC_IMM
, 0, stack_opnd_size
,
1016 GINSN_DST_REG
, REG_SP
, 0);
1017 ginsn_set_where (ginsn
);
1020 mem_reg
= (i
.base_reg
) ? i
.base_reg
: i
.index_reg
;
1021 /* Use dummy register if no base or index. Unlike other opcodes,
1022 ginsns must be generated as this affect stack pointer. */
1023 dw2_regnum
= (mem_reg
1024 ? ginsn_dw2_regnum (mem_reg
)
1025 : GINSN_DW2_REGNUM_RSI_DUMMY
);
1028 dw2_regnum
= ginsn_dw2_regnum (i
.op
[0].regs
);
1029 ginsn_next
= ginsn_new_store (insn_end_sym
, false,
1030 GINSN_SRC_INDIRECT
, dw2_regnum
,
1031 GINSN_DST_INDIRECT
, REG_SP
, 0);
1032 ginsn_set_where (ginsn_next
);
1033 gas_assert (!ginsn_link_next (ginsn
, ginsn_next
));
1035 else if (i
.tm
.extension_opcode
== 4 || i
.tm
.extension_opcode
== 2)
1036 ginsn
= x86_ginsn_indirect_branch (insn_end_sym
);
1039 case 0xc2: /* ret imm16. */
1040 case 0xc3: /* ret. */
1041 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1044 ginsn
= ginsn_new_return (insn_end_sym
, true);
1045 ginsn_set_where (ginsn
);
1049 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1052 ginsn
= x86_ginsn_enter (insn_end_sym
);
1056 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1059 ginsn
= x86_ginsn_leave (insn_end_sym
);
1062 case 0xe0 ... 0xe2: /* loop / loope / loopne. */
1063 case 0xe3: /* jecxz / jrcxz. */
1064 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1066 ginsn
= x86_ginsn_jump (insn_end_sym
, true);
1067 ginsn_set_where (ginsn
);
1071 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1073 /* PS: SCFI machinery does not care about which func is being
1074 called. OK to skip that info. */
1075 ginsn
= ginsn_new_call (insn_end_sym
, true,
1076 GINSN_SRC_SYMBOL
, 0, NULL
);
1077 ginsn_set_where (ginsn
);
1080 /* PS: opcode 0xe9 appears only after relaxation. Skip here. */
1082 /* If opcode_space != SPACE_BASE, this is not a jmp insn. Skip it
1083 for GINSN_GEN_SCFI. */
1084 if (i
.tm
.opcode_space
!= SPACE_BASE
)
1086 /* Unconditional jmp. */
1087 ginsn
= x86_ginsn_jump (insn_end_sym
, false);
1088 ginsn_set_where (ginsn
);
1092 /* TBD_GINSN_GEN_NOT_SCFI: Skip all other opcodes uninteresting for
1093 GINSN_GEN_SCFI mode. */
1097 if (!ginsn
&& !x86_ginsn_safe_to_skip_p ())
1099 /* For all unhandled insns that are not whitelisted, check that they do
1100 not impact SCFI correctness. */
1101 err
= x86_ginsn_unhandled ();
1104 case X86_GINSN_UNHANDLED_NONE
:
1106 case X86_GINSN_UNHANDLED_DEST_REG
:
1107 /* Not all writes to REG_FP are harmful in context of SCFI. Simply
1108 generate a GINSN_TYPE_OTHER with destination set to the
1109 appropriate register. The SCFI machinery will bail out if this
1110 ginsn affects SCFI correctness. */
1111 dw2_regnum
= ginsn_dw2_regnum (i
.op
[i
.operands
- 1].regs
);
1112 ginsn
= ginsn_new_other (insn_end_sym
, true,
1115 GINSN_DST_REG
, dw2_regnum
);
1116 ginsn_set_where (ginsn
);
1118 case X86_GINSN_UNHANDLED_CFG
:
1119 case X86_GINSN_UNHANDLED_STACKOP
:
1120 as_bad (_("SCFI: unhandled op %#x may cause incorrect CFI"), opcode
);
1122 case X86_GINSN_UNHANDLED_UNEXPECTED
:
1123 as_bad (_("SCFI: unexpected op %#x may cause incorrect CFI"),