[PATCH] opcodes/i386-dis.c is not thread-safe
H.J. Lu
hjl.tools@gmail.com
Tue Jan 4 17:47:12 GMT 2022
On Tue, Jan 04, 2022 at 09:38:40AM -0800, Vladimir Mezentsev via Binutils wrote:
> Ping.
>
>
> -------- Forwarded Message --------
> Subject: [PATCH] opcodes/i386-dis.c is not thread-safe
> Date: Mon, 20 Dec 2021 15:04:17 -0800
> From: vladimir.mezentsev@oracle.com
> To: binutils@sourceware.org
>
>
>
> From: Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
>
> We plan to use print_insn_i386_att, print_insn_i386_intel and
> print_insn_i386 in a multithreaded application.
> These functions are not thread safe due to the use of static variables.
>
> Tested on x86_64-pc-linux-gnu.
>
> opcodes/ChangeLog:
> 2021-12-20 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
>
> * opcodes/i386-dis.c: Make print_insn_i386_att, print_insn_i386_intel
> and print_insn_i386 thread-safe
> ---
> opcodes/i386-dis.c | 3488 ++++++++++++++++++++++----------------------
> 1 file changed, 1754 insertions(+), 1734 deletions(-)
>
> diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
> index de3f245cb5..8ca1083333 100644
> --- a/opcodes/i386-dis.c
> +++ b/opcodes/i386-dis.c
> @@ -40,81 +40,82 @@
> #include "safe-ctype.h"
> #include <setjmp.h>
> -
> -static int print_insn (bfd_vma, disassemble_info *);
> -static void dofloat (int);
> -static void OP_ST (int, int);
> -static void OP_STi (int, int);
> -static int putop (const char *, int);
> -static void oappend (const char *);
> -static void append_seg (void);
> -static void OP_indirE (int, int);
> -static void print_operand_value (char *, int, bfd_vma);
> -static void OP_E_memory (int, int);
> -static void print_displacement (char *, bfd_vma);
> -static void OP_E (int, int);
> -static void OP_G (int, int);
> -static bfd_vma get64 (void);
> -static bfd_signed_vma get32 (void);
> -static bfd_signed_vma get32s (void);
> -static int get16 (void);
> -static void set_op (bfd_vma, int);
> -static void OP_Skip_MODRM (int, int);
> -static void OP_REG (int, int);
> -static void OP_IMREG (int, int);
> -static void OP_I (int, int);
> -static void OP_I64 (int, int);
> -static void OP_sI (int, int);
> -static void OP_J (int, int);
> -static void OP_SEG (int, int);
> -static void OP_DIR (int, int);
> -static void OP_OFF (int, int);
> -static void OP_OFF64 (int, int);
> -static void ptr_reg (int, int);
> -static void OP_ESreg (int, int);
> -static void OP_DSreg (int, int);
> -static void OP_C (int, int);
> -static void OP_D (int, int);
> -static void OP_T (int, int);
> -static void OP_MMX (int, int);
> -static void OP_XMM (int, int);
> -static void OP_EM (int, int);
> -static void OP_EX (int, int);
> -static void OP_EMC (int,int);
> -static void OP_MXC (int,int);
> -static void OP_MS (int, int);
> -static void OP_XS (int, int);
> -static void OP_M (int, int);
> -static void OP_VEX (int, int);
> -static void OP_VexR (int, int);
> -static void OP_VexW (int, int);
> -static void OP_Rounding (int, int);
> -static void OP_REG_VexI4 (int, int);
> -static void OP_VexI4 (int, int);
> -static void PCLMUL_Fixup (int, int);
> -static void VPCMP_Fixup (int, int);
> -static void VPCOM_Fixup (int, int);
> -static void OP_0f07 (int, int);
> -static void OP_Monitor (int, int);
> -static void OP_Mwait (int, int);
> -static void NOP_Fixup1 (int, int);
> -static void NOP_Fixup2 (int, int);
> -static void OP_3DNowSuffix (int, int);
> -static void CMP_Fixup (int, int);
> -static void BadOp (void);
> -static void REP_Fixup (int, int);
> -static void SEP_Fixup (int, int);
> -static void BND_Fixup (int, int);
> -static void NOTRACK_Fixup (int, int);
> -static void HLE_Fixup1 (int, int);
> -static void HLE_Fixup2 (int, int);
> -static void HLE_Fixup3 (int, int);
> -static void CMPXCHG8B_Fixup (int, int);
> -static void XMM_Fixup (int, int);
> -static void FXSAVE_Fixup (int, int);
> -
> -static void MOVSXD_Fixup (int, int);
> -static void DistinctDest_Fixup (int, int);
> +typedef struct instr_info instr_info;
> +
> +static int print_insn (bfd_vma, instr_info *);
> +static void dofloat (instr_info *, int);
> +static void OP_ST (instr_info *, int, int);
> +static void OP_STi (instr_info *, int, int);
> +static int putop (instr_info *, const char *, int);
> +static void oappend (instr_info *, const char *);
> +static void append_seg (instr_info *);
> +static void OP_indirE (instr_info *, int, int);
> +static void print_operand_value (instr_info *, char *, int, bfd_vma);
> +static void OP_E_memory (instr_info *, int, int);
> +static void print_displacement (instr_info *, char *, bfd_vma);
> +static void OP_E (instr_info *, int, int);
> +static void OP_G (instr_info *, int, int);
> +static bfd_vma get64 (instr_info *);
> +static bfd_signed_vma get32 (instr_info *);
> +static bfd_signed_vma get32s (instr_info *);
> +static int get16 (instr_info *);
> +static void set_op (instr_info *, bfd_vma, int);
> +static void OP_Skip_MODRM (instr_info *, int, int);
> +static void OP_REG (instr_info *, int, int);
> +static void OP_IMREG (instr_info *, int, int);
> +static void OP_I (instr_info *, int, int);
> +static void OP_I64 (instr_info *, int, int);
> +static void OP_sI (instr_info *, int, int);
> +static void OP_J (instr_info *, int, int);
> +static void OP_SEG (instr_info *, int, int);
> +static void OP_DIR (instr_info *, int, int);
> +static void OP_OFF (instr_info *, int, int);
> +static void OP_OFF64 (instr_info *, int, int);
> +static void ptr_reg (instr_info *, int, int);
> +static void OP_ESreg (instr_info *, int, int);
> +static void OP_DSreg (instr_info *, int, int);
> +static void OP_C (instr_info *, int, int);
> +static void OP_D (instr_info *, int, int);
> +static void OP_T (instr_info *, int, int);
> +static void OP_MMX (instr_info *, int, int);
> +static void OP_XMM (instr_info *, int, int);
> +static void OP_EM (instr_info *, int, int);
> +static void OP_EX (instr_info *, int, int);
> +static void OP_EMC (instr_info *, int,int);
> +static void OP_MXC (instr_info *, int,int);
> +static void OP_MS (instr_info *, int, int);
> +static void OP_XS (instr_info *, int, int);
> +static void OP_M (instr_info *, int, int);
> +static void OP_VEX (instr_info *, int, int);
> +static void OP_VexR (instr_info *, int, int);
> +static void OP_VexW (instr_info *, int, int);
> +static void OP_Rounding (instr_info *, int, int);
> +static void OP_REG_VexI4 (instr_info *, int, int);
> +static void OP_VexI4 (instr_info *, int, int);
> +static void PCLMUL_Fixup (instr_info *, int, int);
> +static void VPCMP_Fixup (instr_info *, int, int);
> +static void VPCOM_Fixup (instr_info *, int, int);
> +static void OP_0f07 (instr_info *, int, int);
> +static void OP_Monitor (instr_info *, int, int);
> +static void OP_Mwait (instr_info *, int, int);
> +static void NOP_Fixup1 (instr_info *, int, int);
> +static void NOP_Fixup2 (instr_info *, int, int);
> +static void OP_3DNowSuffix (instr_info *, int, int);
> +static void CMP_Fixup (instr_info *, int, int);
> +static void BadOp (instr_info *);
> +static void REP_Fixup (instr_info *, int, int);
> +static void SEP_Fixup (instr_info *, int, int);
> +static void BND_Fixup (instr_info *, int, int);
> +static void NOTRACK_Fixup (instr_info *, int, int);
> +static void HLE_Fixup1 (instr_info *, int, int);
> +static void HLE_Fixup2 (instr_info *, int, int);
> +static void HLE_Fixup3 (instr_info *, int, int);
> +static void CMPXCHG8B_Fixup (instr_info *, int, int);
> +static void XMM_Fixup (instr_info *, int, int);
> +static void FXSAVE_Fixup (instr_info *, int, int);
> +
> +static void MOVSXD_Fixup (instr_info *, int, int);
> +static void DistinctDest_Fixup (instr_info *, int, int);
> struct dis_private {
> /* Points to first byte not fetched. */
> @@ -132,15 +133,138 @@ enum address_mode
> mode_64bit
> };
> -enum address_mode address_mode;
> +enum x86_64_isa
> +{
> + amd64 = 1,
> + intel64
> +};
> +
> +struct instr_info
> +{
> + enum address_mode address_mode;
> +
> + /* Flags for the prefixes for the current instruction. See below. */
> + int prefixes;
> +
> + /* REX prefix the current instruction. See below. */
> + int rex;
> + /* Bits of REX we've already used. */
> + int rex_used;
> +
> + /* Flags for ins->prefixes which we somehow handled when printing the
> + current instruction. */
> + int used_prefixes;
> +
> + /* Flags for EVEX bits which we somehow handled when printing the
> + current instruction. */
> + int evex_used;
> +
> + char obuf[100];
> + char *obufp;
> + char *mnemonicendp;
> + char scratchbuf[100];
> + unsigned char *start_codep;
> + unsigned char *insn_codep;
> + unsigned char *codep;
> + unsigned char *end_codep;
> + int last_lock_prefix;
> + int last_repz_prefix;
> + int last_repnz_prefix;
> + int last_data_prefix;
> + int last_addr_prefix;
> + int last_rex_prefix;
> + int last_seg_prefix;
> + int fwait_prefix;
> + /* The active segment register prefix. */
> + int active_seg_prefix;
> +
> +#define MAX_CODE_LENGTH 15
> + /* We can up to 14 ins->prefixes since the maximum instruction length is
> + 15bytes. */
> + int all_prefixes[MAX_CODE_LENGTH - 1];
> + disassemble_info *info;
> +
> + struct
> + {
> + int mod;
> + int reg;
> + int rm;
> + }
> + modrm;
> + unsigned char need_modrm;
> +
> + struct
> + {
> + int scale;
> + int index;
> + int base;
> + }
> + sib;
> +
> + struct
> + {
> + int register_specifier;
> + int length;
> + int prefix;
> + int w;
> + int evex;
> + int r;
> + int v;
> + int mask_register_specifier;
> + int zeroing;
> + int ll;
> + int b;
> + int no_broadcast;
> + }
> + vex;
> + unsigned char need_vex;
> +
> + const char **names64;
> + const char **names32;
> + const char **names16;
> + const char **names8;
> + const char **names8rex;
> + const char **names_seg;
> + const char *index64;
> + const char *index32;
> + const char **index16;
> + const char **names_bnd;
> + const char **names_mm;
> + const char **names_xmm;
> + const char **names_ymm;
> + const char **names_zmm;
> + const char **names_tmm;
> + const char **names_mask;
> +
> + /* Remember if the current op is a jump instruction. */
> + bool op_is_jump;
> +
> + char op_out[MAX_OPERANDS][100];
> + int op_ad, op_index[MAX_OPERANDS];
> + int two_source_ops;
> + bfd_vma op_address[MAX_OPERANDS];
> + bfd_vma op_riprel[MAX_OPERANDS];
> + bfd_vma start_pc;
> +
> + /*
> + * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
> + * (see topic "Redundant ins->prefixes" in the "Differences from 8086"
> + * section of the "Virtual 8086 Mode" chapter.)
> + * 'pc' should be the address of this instruction, it will
> + * be used to print the target address if this is a relative jump or call
> + * The function returns the length of this instruction in bytes.
> + */
> + char intel_syntax;
> + char intel_mnemonic;
> + char open_char;
> + char close_char;
> + char separator_char;
> + char scale_char;
> +
> + enum x86_64_isa isa64;
> -/* Flags for the prefixes for the current instruction. See below. */
> -static int prefixes;
> +};
Please follow GNU coding standard:
https://www.gnu.org/prep/standards/
contrib/check_GNU_style.py in gcc source:
https://gcc.gnu.org/git?p=gcc.git;a=blob;f=contrib/check_GNU_style.py
and clang-format may help.
H.J.
More information about the Binutils
mailing list