* [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support
@ 2024-11-13 9:53 Hui Li
2024-11-13 9:53 ` [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record Hui Li
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Hui Li @ 2024-11-13 9:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Tiezhu Yang
This series add record/replay and reverse debugging support on LoongArch.
Hui Li (4):
gdb: LoongArch: Add instruction definition for process record
gdb: LoongArch: Add basic process record/replay support
gdb: LoongArch: Add system call support for process record/replay
gdb: Add LoongArch process record/replay support in NEWS and doc
gdb/NEWS | 3 +
gdb/arch/loongarch-insn.h | 1361 ++++++++++++++++++++++++++++++++++
gdb/arch/loongarch-syscall.h | 348 +++++++++
gdb/configure.tgt | 2 +-
gdb/doc/gdb.texinfo | 2 +-
gdb/loongarch-linux-tdep.c | 568 ++++++++++++++
gdb/loongarch-tdep.c | 610 +++++++++++++++
gdb/loongarch-tdep.h | 7 +
gdb/testsuite/lib/gdb.exp | 2 +
9 files changed, 2901 insertions(+), 2 deletions(-)
create mode 100644 gdb/arch/loongarch-insn.h
create mode 100644 gdb/arch/loongarch-syscall.h
--
2.38.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record
2024-11-13 9:53 [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support Hui Li
@ 2024-11-13 9:53 ` Hui Li
2024-11-13 12:03 ` Guinevere Larsen
2024-11-13 9:53 ` [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support Hui Li
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Hui Li @ 2024-11-13 9:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Tiezhu Yang
GDB provides a special process record function that can record a log
of the process execution. The core of this feature is need to record
the execution of all instructions. This patch adds opcode definitions
and judgments in gdb/arch/loongarch-insn.h. This is preparation for
later patch on LoongArch, there is no effect for the other archs with
this patch.
The LoongArch opcode and mask definitions are obtained from
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=opcodes/loongarch-opc.c
LoongArch instruction description refer to the LoongArch Reference Manual:
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
Signed-off-by: Hui Li <lihui@loongson.cn>
---
gdb/arch/loongarch-insn.h | 1361 +++++++++++++++++++++++++++++++++++++
1 file changed, 1361 insertions(+)
create mode 100644 gdb/arch/loongarch-insn.h
diff --git a/gdb/arch/loongarch-insn.h b/gdb/arch/loongarch-insn.h
new file mode 100644
index 00000000000..657ec8a092d
--- /dev/null
+++ b/gdb/arch/loongarch-insn.h
@@ -0,0 +1,1361 @@
+/* Target-dependent code for LoongArch
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* The LoongArch opcode and mask definitions in this file are obtained from
+ https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=opcodes/loongarch-opc.c */
+
+#ifndef ARCH_LOONGARCH_INSN_H
+#define ARCH_LOONGARCH_INSN_H
+
+enum loongarch_insn_opcode
+{
+ /* loongarch fix insn opcode */
+ OP_CLO_W = 0x00001000,
+ OP_CLZ_W = 0x00001400,
+ OP_CTO_W = 0x00001800,
+ OP_CTZ_W = 0x00001c00,
+ OP_CLO_D = 0x00002000,
+ OP_CLZ_D = 0x00002400,
+ OP_CTO_D = 0x00002800,
+ OP_CTZ_D = 0x00002c00,
+ OP_REVB_2H = 0x00003000,
+ OP_REVB_4H = 0x00003400,
+ OP_REVB_2W = 0x00003800,
+ OP_REVB_D = 0x00003c00,
+ OP_REVH_2W = 0x00004000,
+ OP_REVH_D = 0x00004400,
+ OP_BITREV_4B = 0x00004800,
+ OP_BITREV_8B = 0x00004c00,
+ OP_BITREV_W = 0x00005000,
+ OP_BITREV_D = 0x00005400,
+ OP_EXT_W_H = 0x00005800,
+ OP_EXT_W_B = 0x00005c00,
+ OP_RDTIMEL_W = 0x00006000,
+ OP_RDTIMEH_W = 0x00006400,
+ OP_RDTIME_D = 0x00006800,
+ OP_CPUCFG = 0x00006c00,
+ OP_ASRTLE_D = 0x00010000,
+ OP_ASRTGT_D = 0x00018000,
+ OP_ALSL_W = 0x00040000,
+ OP_ALSL_WU = 0x00060000,
+ OP_BYTEPICK_W = 0x00080000,
+ OP_BYTEPICK_D = 0x000c0000,
+ OP_ADD_W = 0x00100000,
+ OP_ADD_D = 0x00108000,
+ OP_SUB_W = 0x00110000,
+ OP_SUB_D = 0x00118000,
+ OP_SLT = 0x00120000,
+ OP_SLTU = 0x00128000,
+ OP_MASKEQZ = 0x00130000,
+ OP_MASKNEZ = 0x00138000,
+ OP_NOR = 0x00140000,
+ OP_AND = 0x00148000,
+ OP_OR = 0x00150000,
+ OP_XOR = 0x00158000,
+ OP_ORN = 0x00160000,
+ OP_ANDN = 0x00168000,
+ OP_SLL_W = 0x00170000,
+ OP_SRL_W = 0x00178000,
+ OP_SRA_W = 0x00180000,
+ OP_SLL_D = 0x00188000,
+ OP_SRL_D = 0x00190000,
+ OP_SRA_D = 0x00198000,
+ OP_ROTR_W = 0x001b0000,
+ OP_ROTR_D = 0x001b8000,
+ OP_MUL_W = 0x001c0000,
+ OP_MULH_W = 0x001c8000,
+ OP_MULH_WU = 0x001d0000,
+ OP_MUL_D = 0x001d8000,
+ OP_MULH_D = 0x001e0000,
+ OP_MULH_DU = 0x001e8000,
+ OP_MULW_D_W = 0x001f0000,
+ OP_MULW_D_WU = 0x001f8000,
+ OP_DIV_W = 0x00200000,
+ OP_MOD_W = 0x00208000,
+ OP_DIV_WU = 0x00210000,
+ OP_MOD_WU = 0x00218000,
+ OP_DIV_D = 0x00220000,
+ OP_MOD_D = 0x00228000,
+ OP_DIV_DU = 0x00230000,
+ OP_MOD_DU = 0x00238000,
+ OP_CRC_W_B_W = 0x00240000,
+ OP_CRC_W_H_W = 0x00248000,
+ OP_CRC_W_W_W = 0x00250000,
+ OP_CRC_W_D_W = 0x00258000,
+ OP_CRCC_W_B_W = 0x00260000,
+ OP_CRCC_W_H_W = 0x00268000,
+ OP_CRCC_W_W_W = 0x00270000,
+ OP_CRCC_W_D_W = 0x00278000,
+ OP_BREAK = 0x002a0000,
+ OP_DBCL = 0x002a8000,
+ OP_SYSCALL = 0x002b0000,
+ OP_ALSL_D = 0x002c0000,
+ OP_SLLI_W = 0x00408000,
+ OP_SLLI_D = 0x00410000,
+ OP_SRLI_W = 0x00448000,
+ OP_SRLI_D = 0x00450000,
+ OP_SRAI_W = 0x00488000,
+ OP_SRAI_D = 0x00490000,
+ OP_ROTRI_W = 0x004c8000,
+ OP_ROTRI_D = 0x004d0000,
+ OP_BSTRINS_W = 0x00600000,
+ OP_BSTRPICK_W = 0x00608000,
+ OP_BSTRINS_D = 0x00800000,
+ OP_BSTRPICK_D = 0x00c00000,
+
+ /* loongarch single float insn opcode */
+ OP_FADD_S = 0x01008000,
+ OP_SUB_S = 0x01028000,
+ OP_MUL_S = 0x01048000,
+ OP_FDIV_S = 0x01068000,
+ OP_FMAX_S = 0x01088000,
+ OP_FMIN_S = 0x010a8000,
+ OP_FMAXA_S = 0x010c8000,
+ OP_FMINA_S = 0x010e8000,
+ OP_FSCALEB_S = 0x01108000,
+ OP_FCOPYSIGN_S = 0x01128000,
+ OP_FABS_S = 0x01140400,
+ OP_FNEG_S = 0x01141400,
+ OP_FLOGB_S = 0x01142400,
+ OP_FCLASS_S = 0x01143400,
+ OP_FSQRT_S = 0x01144400,
+ OP_FRECIP_S = 0x01145400,
+ OP_FRSQRT_S = 0x01146400,
+ OP_FRECIPE_S = 0x01147400,
+ OP_FRSQRTE_S = 0x01148400,
+ OP_FMOV_S = 0x01149400,
+ OP_MOVGR2FR_W = 0x0114a400,
+ OP_MOVGR2FRH_W = 0x0114ac00,
+ OP_MOVFR2GR_S = 0x0114b400,
+ OP_MOVFRH2GR_S = 0x0114bc00,
+ OP_MOVGR2FCSR = 0x0114c000,
+ OP_MOVFCSR2GR = 0x0114c800,
+ OP_MOVFR2CF = 0x0114d000,
+ OP_MOVCF2FR = 0x0114d400,
+ OP_MOVGR2CF = 0x0114d800,
+ OP_MOVCF2GR = 0x0114dc00,
+ OP_FTINTRM_W_S = 0x011a0400,
+ OP_FTINTRM_L_S = 0x011a2400,
+ OP_FTINTRP_W_S = 0x011a4400,
+ OP_FTINTRP_L_S = 0x011a6400,
+ OP_FTINTRZ_W_S = 0x011a8400,
+ OP_FTINTRZ_L_S = 0x011aa400,
+ OP_FTINTRNE_W_S = 0x011ac400,
+ OP_FTINTRNE_L_S = 0x011ae400,
+ OP_FTINT_W_S = 0x011b0400,
+ OP_FTINT_L_S = 0x011b2400,
+ OP_FFINT_S_W = 0x011d1000,
+ OP_FFINT_S_L = 0x011d1800,
+ OP_FRINT_S = 0x011e4400,
+
+ /* loongarch double float insn opcode */
+ OP_FADD_D = 0x01010000,
+ OP_FSUB_D = 0x01030000,
+ OP_FMUL_D = 0x01050000,
+ OP_FDIV_D = 0x01070000,
+ OP_FMAX_D = 0x01090000,
+ OP_FMIN_D = 0x010b0000,
+ OP_FMAXA_D = 0x010d0000,
+ OP_FMINA_D = 0x010f0000,
+ OP_FSCALEB_D = 0x01110000,
+ OP_FCOPYSIGN_D = 0x01130000,
+ OP_FABS_D = 0x01140800,
+ OP_FNEG_D = 0x01141800,
+ OP_FLOGB_D = 0x01142800,
+ OP_FCLASS_D = 0x01143800,
+ OP_FSQRT_D = 0x01144800,
+ OP_FRECIP_D = 0x01145800,
+ OP_FRSQRT_D = 0x01146800,
+ OP_FRECIPE_D = 0x01147800,
+ OP_FRSQRTE_D = 0x01148800,
+ OP_FMOV_D = 0x01149800,
+ OP_MOVGR2FR_D = 0x0114a800,
+ OP_MOVFR2GR_D = 0x0114b800,
+ OP_FCVT_S_D = 0x01191800,
+ OP_FCVT_D_S = 0x01192400,
+ OP_FTINTRM_W_D = 0x011a0800,
+ OP_FTINTRM_L_D = 0x011a2800,
+ OP_FTINTRP_W_D = 0x011a4800,
+ OP_FTINTRP_L_D = 0x011a6800,
+ OP_FTINTRZ_W_D = 0x011a8800,
+ OP_FTINTRZ_L_D = 0x011aa800,
+ OP_FTINTRNE_W_D = 0x011ac800,
+ OP_FTINTRNE_L_D = 0x011ae800,
+ OP_FTINT_W_D = 0x011b0800,
+ OP_FTINT_L_D = 0x011b2800,
+ OP_FFINT_D_W = 0x011d2000,
+ OP_FFINT_D_L = 0x011d2800,
+ OP_FRINT_D = 0x011e4800,
+
+ /* loongarch imm insn opcode */
+ OP_SLTI = 0x02000000,
+ OP_SLTUI = 0x02400000,
+ OP_ADDI_W = 0x02800000,
+ OP_ADDI_D = 0x02c00000,
+ OP_LU52I_D = 0x03000000,
+ OP_ANDI = 0x03400000,
+ OP_ORI = 0x03800000,
+ OP_XORI = 0x03c00000,
+ OP_ADDU16I_D = 0x10000000,
+ OP_LU12I_W = 0x14000000,
+ OP_LU32I_D = 0x16000000,
+ OP_PCADDI = 0x18000000,
+ OP_PCALAU12I = 0x1a000000,
+ OP_PCADDU12I = 0x1c000000,
+ OP_PCADDU18I = 0x1e000000,
+
+ /* loongarch privilege insn opcode */
+ OP_CSRRD = 0x04000000,
+ OP_CSRWR = 0x04000020,
+ OP_CSRXCHG = 0x04000000,
+ OP_CACOP = 0x06000000,
+ OP_LDDIR = 0x06400000,
+ OP_LDPTE = 0x06440000,
+ OP_IOCSRRD_B = 0x06480000,
+ OP_IOCSRRD_H = 0x06480400,
+ OP_IOCSRRD_W = 0x06480800,
+ OP_IOCSRRD_D = 0x06480c00,
+ OP_IOCSRWR_B = 0x06481000,
+ OP_IOCSRWR_H = 0x06481400,
+ OP_IOCSRWR_W = 0x06481800,
+ OP_IOCSRWR_D = 0x06481c00,
+ OP_TLBCLR = 0x06482000,
+ OP_TLBFLUSH = 0x06482400,
+ OP_TLBSRCH = 0x06482800,
+ OP_TLBRD = 0x06482c00,
+ OP_TLBWR = 0x06483000,
+ OP_TLBFILL = 0x06483400,
+ OP_ERTN = 0x06483800,
+ OP_IDLE = 0x06488000,
+ OP_INVTLB = 0x06498000,
+
+ /* loongarch 4opt single float insn opcode */
+ OP_FMADD_S = 0x08100000,
+ OP_FMSUB_S = 0x08500000,
+ OP_FNMADD_S = 0x08900000,
+ OP_FNMSUB_S = 0x08d00000,
+ OP_FCMP_CAF_S = 0x0c100000,
+ OP_FCMP_SAF_S = 0x0c108000,
+ OP_FCMP_CLT_S = 0x0c110000,
+ OP_FCMP_SLT_S = 0x0c118000,
+ OP_FCMP_SGT_S = 0x0c118000,
+ OP_FCMP_CEQ_S = 0x0c120000,
+ OP_FCMP_SEQ_S = 0x0c128000,
+ OP_FCMP_CLE_S = 0x0c130000,
+ OP_FCMP_SLE_S = 0x0c138000,
+ OP_FCMP_SGE_S = 0x0c138000,
+ OP_FCMP_CUN_S = 0x0c140000,
+ OP_FCMP_SUN_S = 0x0c148000,
+ OP_FCMP_CULT_S = 0x0c150000,
+ OP_FCMP_CUGT_S = 0x0c150000,
+ OP_FCMP_SULT_S = 0x0c158000,
+ OP_FCMP_CUEQ_S = 0x0c160000,
+ OP_FCMP_SUEQ_S = 0x0c168000,
+ OP_FCMP_CULE_S = 0x0c170000,
+ OP_FCMP_CUGE_S = 0x0c170000,
+ OP_FCMP_SULE_S = 0x0c178000,
+ OP_FCMP_CNE_S = 0x0c180000,
+ OP_FCMP_SNE_S = 0x0c188000,
+ OP_FCMP_COR_S = 0x0c1a0000,
+ OP_FCMP_SOR_S = 0x0c1a8000,
+ OP_FCMP_CUNE_S = 0x0c1c0000,
+ OP_FCMP_SUNE_S = 0x0c1c8000,
+ OP_FSEL = 0x0d000000,
+
+ /* loongarch 4opt double float insn opcode */
+ OP_FMADD_D = 0x08200000,
+ OP_FMSUB_D = 0x08600000,
+ OP_FNMADD_D = 0x08a00000,
+ OP_FNMSUB_D = 0x08e00000,
+ OP_FCMP_CAF_D = 0x0c200000,
+ OP_FCMP_SAF_D = 0x0c208000,
+ OP_FCMP_CLT_D = 0x0c210000,
+ OP_FCMP_SLT_D = 0x0c218000,
+ OP_FCMP_SGT_D = 0x0c218000,
+ OP_FCMP_CEQ_D = 0x0c220000,
+ OP_FCMP_SEQ_D = 0x0c228000,
+ OP_FCMP_CLE_D = 0x0c230000,
+ OP_FCMP_SLE_D = 0x0c238000,
+ OP_FCMP_SGE_D = 0x0c238000,
+ OP_FCMP_CUN_D = 0x0c240000,
+ OP_FCMP_SUN_D = 0x0c248000,
+ OP_FCMP_CULT_D = 0x0c250000,
+ OP_FCMP_CUGT_D = 0x0c250000,
+ OP_FCMP_SULT_D = 0x0c258000,
+ OP_FCMP_CUEQ_D = 0x0c260000,
+ OP_FCMP_SUEQ_D = 0x0c268000,
+ OP_FCMP_CULE_D = 0x0c270000,
+ OP_FCMP_CUGE_D = 0x0c270000,
+ OP_FCMP_SULE_D = 0x0c278000,
+ OP_FCMP_CNE_D = 0x0c280000,
+ OP_FCMP_SNE_D = 0x0c288000,
+ OP_FCMP_COR_D = 0x0c2a0000,
+ OP_FCMP_SOR_D = 0x0c2a8000,
+ OP_FCMP_CUNE_D = 0x0c2c0000,
+ OP_FCMP_SUNE_D = 0x0c2c8000,
+
+ /* loongarch load store insn opcode */
+ OP_LL_W = 0x20000000,
+ OP_SC_W = 0x21000000,
+ OP_LL_D = 0x22000000,
+ OP_SC_D = 0x23000000,
+ OP_LDPTR_W = 0x24000000,
+ OP_STPTR_W = 0x25000000,
+ OP_LDPTR_D = 0x26000000,
+ OP_STPTR_D = 0x27000000,
+ OP_LD_B = 0x28000000,
+ OP_LD_H = 0x28400000,
+ OP_LD_W = 0x28800000,
+ OP_LD_D = 0x28c00000,
+ OP_ST_B = 0x29000000,
+ OP_ST_H = 0x29400000,
+ OP_ST_W = 0x29800000,
+ OP_ST_D = 0x29c00000,
+ OP_LD_BU = 0x2a000000,
+ OP_LD_HU = 0x2a400000,
+ OP_LD_WU = 0x2a800000,
+ OP_PRELD = 0x2ac00000,
+ OP_LDX_B = 0x38000000,
+ OP_LDX_H = 0x38040000,
+ OP_LDX_W = 0x38080000,
+ OP_LDX_D = 0x380c0000,
+ OP_STX_B = 0x38100000,
+ OP_STX_H = 0x38140000,
+ OP_STX_W = 0x38180000,
+ OP_STX_D = 0x381c0000,
+ OP_LDX_BU = 0x38200000,
+ OP_LDX_HU = 0x38240000,
+ OP_LDX_WU = 0x38280000,
+ OP_PRELDX = 0x382c0000,
+ OP_SC_Q = 0x38570000,
+ OP_LLACQ_W = 0x38578000,
+ OP_SCREL_W = 0x38578400,
+ OP_LLACQ_D = 0x38578800,
+ OP_SCREL_D = 0x38578c00,
+ OP_AMCAS_B = 0x38580000,
+ OP_AMCAS_H = 0x38588000,
+ OP_AMCAS_W = 0x38590000,
+ OP_AMCAS_D = 0x38598000,
+ OP_AMCAS_DB_B = 0x385a0000,
+ OP_AMCAS_DB_H = 0x385a8000,
+ OP_AMCAS_DB_W = 0x385b0000,
+ OP_AMCAS_DB_D = 0x385b8000,
+ OP_AMSWAP_B = 0x385c0000,
+ OP_AMSWAP_H = 0x385c8000,
+ OP_AMADD_B = 0x385d0000,
+ OP_AMADD_H = 0x385d8000,
+ OP_AMSWAP_DB_B = 0x385e0000,
+ OP_AMSWAP_DB_H = 0x385e8000,
+ OP_AMADD_DB_B = 0x385f0000,
+ OP_AMADD_DB_H = 0x385f8000,
+ OP_AMSWAP_W = 0x38600000,
+ OP_AMSWAP_D = 0x38608000,
+ OP_AMADD_W = 0x38610000,
+ OP_AMADD_D = 0x38618000,
+ OP_AMAND_W = 0x38620000,
+ OP_AMAND_D = 0x38628000,
+ OP_AMOR_W = 0x38630000,
+ OP_AMOR_D = 0x38638000,
+ OP_AMXOR_W = 0x38640000,
+ OP_AMXOR_D = 0x38648000,
+ OP_AMMAX_W = 0x38650000,
+ OP_AMMAX_D = 0x38658000,
+ OP_AMMIN_W = 0x38660000,
+ OP_AMMIN_D = 0x38668000,
+ OP_AMMAX_WU = 0x38670000,
+ OP_AMMAX_DU = 0x38678000,
+ OP_AMMIN_WU = 0x38680000,
+ OP_AMMIN_DU = 0x38688000,
+ OP_AMSWAP_DB_W = 0x38690000,
+ OP_AMSWAP_DB_D = 0x38698000,
+ OP_AMADD_DB_W = 0x386a0000,
+ OP_AMADD_DB_D = 0x386a8000,
+ OP_AMAND_DB_W = 0x386b0000,
+ OP_AMAND_DB_D = 0x386b8000,
+ OP_AMOR_DB_W = 0x386c0000,
+ OP_AMOR_DB_D = 0x386c8000,
+ OP_AMXOR_DB_W = 0x386d0000,
+ OP_AMXOR_DB_D = 0x386d8000,
+ OP_AMMAX_DB_W = 0x386e0000,
+ OP_AMMAX_DB_D = 0x386e8000,
+ OP_AMMIN_DB_W = 0x386f0000,
+ OP_AMMIN_DB_D = 0x386f8000,
+ OP_AMMAX_DB_WU = 0x38700000,
+ OP_AMMAX_DB_DU = 0x38708000,
+ OP_AMMIN_DB_WU = 0x38710000,
+ OP_AMMIN_DB_DU = 0x38718000,
+ OP_DBAR = 0x38720000,
+ OP_IBAR = 0x38728000,
+ OP_LDGT_B = 0x38780000,
+ OP_LDGT_H = 0x38788000,
+ OP_LDGT_W = 0x38790000,
+ OP_LDGT_D = 0x38798000,
+ OP_LDLE_B = 0x387a0000,
+ OP_LDLE_H = 0x387a8000,
+ OP_LDLE_W = 0x387b0000,
+ OP_LDLE_D = 0x387b8000,
+ OP_STGT_B = 0x387c0000,
+ OP_STGT_H = 0x387c8000,
+ OP_STGT_W = 0x387d0000,
+ OP_STGT_D = 0x387d8000,
+ OP_STLE_B = 0x387e0000,
+ OP_STLE_H = 0x387e8000,
+ OP_STLE_W = 0x387f0000,
+ OP_STLE_D = 0x387f8000,
+ OP_VLD = 0x2c000000,
+ OP_VST = 0x2c400000,
+ OP_XVLD = 0x2c800000,
+ OP_XVST = 0x2cc00000,
+
+ /* loongarch single float load store insn opcode */
+ OP_FLD_S = 0x2b000000,
+ OP_FST_S = 0x2b400000,
+ OP_FLDX_S = 0x38300000,
+ OP_FSTX_S = 0x38380000,
+ OP_FLDGT_S = 0x38740000,
+ OP_FLDLE_S = 0x38750000,
+ OP_FSTGT_S = 0x38760000,
+ OP_FSTLE_S = 0x38770000,
+
+ /* loongarch double float load store insn opcode */
+ OP_FLD_D = 0x2b800000,
+ OP_FST_D = 0x2bc00000,
+ OP_FLDX_D = 0x38340000,
+ OP_FSTX_D = 0x383c0000,
+ OP_FLDGT_D = 0x38748000,
+ OP_FLDLE_D = 0x38758000,
+ OP_FSTGT_D = 0x38768000,
+ OP_FSTLE_D = 0x38778000,
+
+ /* loongarch float jmp insn opcode */
+ OP_BCEQZ = 0x48000000,
+ OP_BCNEZ = 0x48000100,
+
+ /* loongarch jmp insn opcode */
+ OP_BEQZ = 0x40000000,
+ OP_BNEZ = 0x44000000,
+ OP_JIRL = 0x4c000000,
+ OP_B = 0x50000000,
+ OP_BL = 0x54000000,
+ OP_BEQ = 0x58000000,
+ OP_BNE = 0x5c000000,
+ OP_BLT = 0x60000000,
+ OP_BGE = 0x64000000,
+ OP_BLTU = 0x68000000,
+ OP_BGEU = 0x6c000000,
+};
+
+enum loongarch_insn_mask
+{
+ /* loongarch fix insn mask */
+ MASK_CLO_W = 0xfffffc00,
+ MASK_CLZ_W = 0xfffffc00,
+ MASK_CTO_W = 0xfffffc00,
+ MASK_CTZ_W = 0xfffffc00,
+ MASK_CLO_D = 0xfffffc00,
+ MASK_CLZ_D = 0xfffffc00,
+ MASK_CTO_D = 0xfffffc00,
+ MASK_CTZ_D = 0xfffffc00,
+ MASK_REVB_2H = 0xfffffc00,
+ MASK_REVB_4H = 0xfffffc00,
+ MASK_REVB_2W = 0xfffffc00,
+ MASK_REVB_D = 0xfffffc00,
+ MASK_REVH_2W = 0xfffffc00,
+ MASK_REVH_D = 0xfffffc00,
+ MASK_BITREV_4B = 0xfffffc00,
+ MASK_BITREV_8B = 0xfffffc00,
+ MASK_BITREV_W = 0xfffffc00,
+ MASK_BITREV_D = 0xfffffc00,
+ MASK_EXT_W_H = 0xfffffc00,
+ MASK_EXT_W_B = 0xfffffc00,
+ MASK_RDTIMEL_W = 0xfffffc00,
+ MASK_RDTIMEH_W = 0xfffffc00,
+ MASK_RDTIME_D = 0xfffffc00,
+ MASK_CPUCFG = 0xfffffc00,
+ MASK_ASRTLE_D = 0xffff801f,
+ MASK_ASRTGT_D = 0xffff801f,
+ MASK_ALSL_W = 0xfffe0000,
+ MASK_ALSL_WU = 0xfffe0000,
+ MASK_BYTEPICK_W = 0xfffe0000,
+ MASK_BYTEPICK_D = 0xfffc0000,
+ MASK_ADD_W = 0xffff8000,
+ MASK_ADD_D = 0xffff8000,
+ MASK_SUB_W = 0xffff8000,
+ MASK_SUB_D = 0xffff8000,
+ MASK_SLT = 0xffff8000,
+ MASK_SLTU = 0xffff8000,
+ MASK_MASKEQZ = 0xffff8000,
+ MASK_MASKNEZ = 0xffff8000,
+ MASK_NOR = 0xffff8000,
+ MASK_AND = 0xffff8000,
+ MASK_OR = 0xffff8000,
+ MASK_XOR = 0xffff8000,
+ MASK_ORN = 0xffff8000,
+ MASK_ANDN = 0xffff8000,
+ MASK_SLL_W = 0xffff8000,
+ MASK_SRL_W = 0xffff8000,
+ MASK_SRA_W = 0xffff8000,
+ MASK_SLL_D = 0xffff8000,
+ MASK_SRL_D = 0xffff8000,
+ MASK_SRA_D = 0xffff8000,
+ MASK_ROTR_W = 0xffff8000,
+ MASK_ROTR_D = 0xffff8000,
+ MASK_MUL_W = 0xffff8000,
+ MASK_MULH_W = 0xffff8000,
+ MASK_MULH_WU = 0xffff8000,
+ MASK_MUL_D = 0xffff8000,
+ MASK_MULH_D = 0xffff8000,
+ MASK_MULH_DU = 0xffff8000,
+ MASK_MULW_D_W = 0xffff8000,
+ MASK_MULW_D_WU = 0xffff8000,
+ MASK_DIV_W = 0xffff8000,
+ MASK_MOD_W = 0xffff8000,
+ MASK_DIV_WU = 0xffff8000,
+ MASK_MOD_WU = 0xffff8000,
+ MASK_DIV_D = 0xffff8000,
+ MASK_MOD_D = 0xffff8000,
+ MASK_DIV_DU = 0xffff8000,
+ MASK_MOD_DU = 0xffff8000,
+ MASK_CRC_W_B_W = 0xffff8000,
+ MASK_CRC_W_H_W = 0xffff8000,
+ MASK_CRC_W_W_W = 0xffff8000,
+ MASK_CRC_W_D_W = 0xffff8000,
+ MASK_CRCC_W_B_W = 0xffff8000,
+ MASK_CRCC_W_H_W = 0xffff8000,
+ MASK_CRCC_W_W_W = 0xffff8000,
+ MASK_CRCC_W_D_W = 0xffff8000,
+ MASK_BREAK = 0xffff8000,
+ MASK_DBCL = 0xffff8000,
+ MASK_SYSCALL = 0xffff8000,
+ MASK_ALSL_D = 0xfffe0000,
+ MASK_SLLI_W = 0xffff8000,
+ MASK_SLLI_D = 0xffff0000,
+ MASK_SRLI_W = 0xffff8000,
+ MASK_SRLI_D = 0xffff0000,
+ MASK_SRAI_W = 0xffff8000,
+ MASK_SRAI_D = 0xffff0000,
+ MASK_ROTRI_W = 0xffff8000,
+ MASK_ROTRI_D = 0xffff0000,
+ MASK_BSTRINS_W = 0xffe08000,
+ MASK_BSTRPICK_W = 0xffe08000,
+ MASK_BSTRINS_D = 0xffc00000,
+ MASK_BSTRPICK_D = 0xffc00000,
+
+ /* loongarch single float insn mask */
+ MASK_FADD_S = 0xffff8000,
+ MASK_SUB_S = 0xffff8000,
+ MASK_MUL_S = 0xffff8000,
+ MASK_FDIV_S = 0xffff8000,
+ MASK_FMAX_S = 0xffff8000,
+ MASK_FMIN_S = 0xffff8000,
+ MASK_FMAXA_S = 0xffff8000,
+ MASK_FMINA_S = 0xffff8000,
+ MASK_FSCALEB_S = 0xffff8000,
+ MASK_FCOPYSIGN_S = 0xffff8000,
+ MASK_FABS_S = 0xfffffc00,
+ MASK_FNEG_S = 0xfffffc00,
+ MASK_FLOGB_S = 0xfffffc00,
+ MASK_FCLASS_S = 0xfffffc00,
+ MASK_FSQRT_S = 0xfffffc00,
+ MASK_FRECIP_S = 0xfffffc00,
+ MASK_FRSQRT_S = 0xfffffc00,
+ MASK_FRECIPE_S = 0xfffffc00,
+ MASK_FRSQRTE_S = 0xfffffc00,
+ MASK_FMOV_S = 0xfffffc00,
+ MASK_MOVGR2FR_W = 0xfffffc00,
+ MASK_MOVGR2FRH_W = 0xfffffc00,
+ MASK_MOVFR2GR_S = 0xfffffc00,
+ MASK_MOVFRH2GR_S = 0xfffffc00,
+ MASK_MOVGR2FCSR = 0xfffffc1c,
+ MASK_MOVFCSR2GR = 0xffffff80,
+ MASK_MOVFR2CF = 0xfffffc18,
+ MASK_MOVCF2FR = 0xffffff00,
+ MASK_MOVGR2CF = 0xfffffc18,
+ MASK_MOVCF2GR = 0xffffff00,
+ MASK_FTINTRM_W_S = 0xfffffc00,
+ MASK_FTINTRM_L_S = 0xfffffc00,
+ MASK_FTINTRP_W_S = 0xfffffc00,
+ MASK_FTINTRP_L_S = 0xfffffc00,
+ MASK_FTINTRZ_W_S = 0xfffffc00,
+ MASK_FTINTRZ_L_S = 0xfffffc00,
+ MASK_FTINTRNE_W_S = 0xfffffc00,
+ MASK_FTINTRNE_L_S = 0xfffffc00,
+ MASK_FTINT_W_S = 0xfffffc00,
+ MASK_FTINT_L_S = 0xfffffc00,
+ MASK_FFINT_S_W = 0xfffffc00,
+ MASK_FFINT_S_L = 0xfffffc00,
+ MASK_FRINT_S = 0xfffffc00,
+
+ /* loongarch double float insn mask */
+ MASK_FADD_D = 0xffff8000,
+ MASK_FSUB_D = 0xffff8000,
+ MASK_FMUL_D = 0xffff8000,
+ MASK_FDIV_D = 0xffff8000,
+ MASK_FMAX_D = 0xffff8000,
+ MASK_FMIN_D = 0xffff8000,
+ MASK_FMAXA_D = 0xffff8000,
+ MASK_FMINA_D = 0xffff8000,
+ MASK_FSCALEB_D = 0xffff8000,
+ MASK_FCOPYSIGN_D = 0xffff8000,
+ MASK_FABS_D = 0xfffffc00,
+ MASK_FNEG_D = 0xfffffc00,
+ MASK_FLOGB_D = 0xfffffc00,
+ MASK_FCLASS_D = 0xfffffc00,
+ MASK_FSQRT_D = 0xfffffc00,
+ MASK_FRECIP_D = 0xfffffc00,
+ MASK_FRSQRT_D = 0xfffffc00,
+ MASK_FRECIPE_D = 0xfffffc00,
+ MASK_FRSQRTE_D = 0xfffffc00,
+ MASK_FMOV_D = 0xfffffc00,
+ MASK_MOVGR2FR_D = 0xfffffc00,
+ MASK_MOVFR2GR_D = 0xfffffc00,
+ MASK_FCVT_S_D = 0xfffffc00,
+ MASK_FCVT_D_S = 0xfffffc00,
+ MASK_FTINTRM_W_D = 0xfffffc00,
+ MASK_FTINTRM_L_D = 0xfffffc00,
+ MASK_FTINTRP_W_D = 0xfffffc00,
+ MASK_FTINTRP_L_D = 0xfffffc00,
+ MASK_FTINTRZ_W_D = 0xfffffc00,
+ MASK_FTINTRZ_L_D = 0xfffffc00,
+ MASK_FTINTRNE_W_D = 0xfffffc00,
+ MASK_FTINTRNE_L_D = 0xfffffc00,
+ MASK_FTINT_W_D = 0xfffffc00,
+ MASK_FTINT_L_D = 0xfffffc00,
+ MASK_FFINT_D_W = 0xfffffc00,
+ MASK_FFINT_D_L = 0xfffffc00,
+ MASK_FRINT_D = 0xfffffc00,
+
+ /* loongarch imm insn mask */
+ MASK_SLTI = 0xfffffc00,
+ MASK_SLTUI = 0xffc00000,
+ MASK_ADDI_W = 0xffc00000,
+ MASK_ADDI_D = 0xffc00000,
+ MASK_LU52I_D = 0xffc00000,
+ MASK_ANDI = 0xffc00000,
+ MASK_ORI = 0xffc00000,
+ MASK_XORI = 0xffc00000,
+ MASK_ADDU16I_D = 0xfc000000,
+ MASK_LU12I_W = 0xfe000000,
+ MASK_LU32I_D = 0xfe000000,
+ MASK_PCADDI = 0xfe000000,
+ MASK_PCALAU12I = 0xfe000000,
+ MASK_PCADDU12I = 0xfe000000,
+ MASK_PCADDU18I = 0xfe000000,
+
+ /* loongarch privilege insn mask */
+ MASK_CSRRD = 0xff0003e0,
+ MASK_CSRWR = 0xff0003e0,
+ MASK_CSRXCHG = 0xff000000,
+ MASK_CACOP = 0xffc00000,
+ MASK_LDDIR = 0xfffc0000,
+ MASK_LDPTE = 0xfffc001f,
+ MASK_IOCSRRD_B = 0xfffffc00,
+ MASK_IOCSRRD_H = 0xfffffc00,
+ MASK_IOCSRRD_W = 0xfffffc00,
+ MASK_IOCSRRD_D = 0xfffffc00,
+ MASK_IOCSRWR_B = 0xfffffc00,
+ MASK_IOCSRWR_H = 0xfffffc00,
+ MASK_IOCSRWR_W = 0xfffffc00,
+ MASK_IOCSRWR_D = 0xfffffc00,
+ MASK_TLBCLR = 0xffffffff,
+ MASK_TLBFLUSH = 0xffffffff,
+ MASK_TLBSRCH = 0xffffffff,
+ MASK_TLBRD = 0xffffffff,
+ MASK_TLBWR = 0xffffffff,
+ MASK_TLBFILL = 0xffffffff,
+ MASK_ERTN = 0xffffffff,
+ MASK_IDLE = 0xffff8000,
+ MASK_INVTLB = 0xffff8000,
+
+ /* loongarch 4opt single float insn mask */
+ MASK_FMADD_S = 0xfff00000,
+ MASK_FMSUB_S = 0xfff00000,
+ MASK_FNMADD_S = 0xfff00000,
+ MASK_FNMSUB_S = 0xfff00000,
+ MASK_FCMP_CAF_S = 0xffff8018,
+ MASK_FCMP_SAF_S = 0xffff8018,
+ MASK_FCMP_CLT_S = 0xffff8018,
+ MASK_FCMP_SLT_S = 0xffff8018,
+ MASK_FCMP_SGT_S = 0xffff8018,
+ MASK_FCMP_CEQ_S = 0xffff8018,
+ MASK_FCMP_SEQ_S = 0xffff8018,
+ MASK_FCMP_CLE_S = 0xffff8018,
+ MASK_FCMP_SLE_S = 0xffff8018,
+ MASK_FCMP_SGE_S = 0xffff8018,
+ MASK_FCMP_CUN_S = 0xffff8018,
+ MASK_FCMP_SUN_S = 0xffff8018,
+ MASK_FCMP_CULT_S = 0xffff8018,
+ MASK_FCMP_CUGT_S = 0xffff8018,
+ MASK_FCMP_SULT_S = 0xffff8018,
+ MASK_FCMP_CUEQ_S = 0xffff8018,
+ MASK_FCMP_SUEQ_S = 0xffff8018,
+ MASK_FCMP_CULE_S = 0xffff8018,
+ MASK_FCMP_CUGE_S = 0xffff8018,
+ MASK_FCMP_SULE_S = 0xffff8018,
+ MASK_FCMP_CNE_S = 0xffff8018,
+ MASK_FCMP_SNE_S = 0xffff8018,
+ MASK_FCMP_COR_S = 0xffff8018,
+ MASK_FCMP_SOR_S = 0xffff8018,
+ MASK_FCMP_CUNE_S = 0xffff8018,
+ MASK_FCMP_SUNE_S = 0xffff8018,
+ MASK_FSEL = 0xfffc0000,
+
+ /* loongarch 4opt double float insn mask */
+ MASK_FMADD_D = 0xfff00000,
+ MASK_FMSUB_D = 0xfff00000,
+ MASK_FNMADD_D = 0xfff00000,
+ MASK_FNMSUB_D = 0xfff00000,
+ MASK_FCMP_CAF_D = 0xffff8018,
+ MASK_FCMP_SAF_D = 0xffff8018,
+ MASK_FCMP_CLT_D = 0xffff8018,
+ MASK_FCMP_SLT_D = 0xffff8018,
+ MASK_FCMP_SGT_D = 0xffff8018,
+ MASK_FCMP_CEQ_D = 0xffff8018,
+ MASK_FCMP_SEQ_D = 0xffff8018,
+ MASK_FCMP_CLE_D = 0xffff8018,
+ MASK_FCMP_SLE_D = 0xffff8018,
+ MASK_FCMP_SGE_D = 0xffff8018,
+ MASK_FCMP_CUN_D = 0xffff8018,
+ MASK_FCMP_SUN_D = 0xffff8018,
+ MASK_FCMP_CULT_D = 0xffff8018,
+ MASK_FCMP_CUGT_D = 0xffff8018,
+ MASK_FCMP_SULT_D = 0xffff8018,
+ MASK_FCMP_CUEQ_D = 0xffff8018,
+ MASK_FCMP_SUEQ_D = 0xffff8018,
+ MASK_FCMP_CULE_D = 0xffff8018,
+ MASK_FCMP_CUGE_D = 0xffff8018,
+ MASK_FCMP_SULE_D = 0xffff8018,
+ MASK_FCMP_CNE_D = 0xffff8018,
+ MASK_FCMP_SNE_D = 0xffff8018,
+ MASK_FCMP_COR_D = 0xffff8018,
+ MASK_FCMP_SOR_D = 0xffff8018,
+ MASK_FCMP_CUNE_D = 0xffff8018,
+ MASK_FCMP_SUNE_D = 0xffff8018,
+
+ /* loongarch load store insn mask */
+ MASK_LL_W = 0xff000000,
+ MASK_SC_W = 0xff000000,
+ MASK_LL_D = 0xff000000,
+ MASK_SC_D = 0xff000000,
+ MASK_LDPTR_W = 0xff000000,
+ MASK_STPTR_W = 0xff000000,
+ MASK_LDPTR_D = 0xff000000,
+ MASK_STPTR_D = 0xff000000,
+ MASK_LD_B = 0xffc00000,
+ MASK_LD_H = 0xffc00000,
+ MASK_LD_W = 0xffc00000,
+ MASK_LD_D = 0xffc00000,
+ MASK_ST_B = 0xffc00000,
+ MASK_ST_H = 0xffc00000,
+ MASK_ST_W = 0xffc00000,
+ MASK_ST_D = 0xffc00000,
+ MASK_LD_BU = 0xffc00000,
+ MASK_LD_HU = 0xffc00000,
+ MASK_LD_WU = 0xffc00000,
+ MASK_PRELD = 0xffc00000,
+ MASK_LDX_B = 0xffff8000,
+ MASK_LDX_H = 0xffff8000,
+ MASK_LDX_W = 0xffff8000,
+ MASK_LDX_D = 0xffff8000,
+ MASK_STX_B = 0xffff8000,
+ MASK_STX_H = 0xffff8000,
+ MASK_STX_W = 0xffff8000,
+ MASK_STX_D = 0xffff8000,
+ MASK_LDX_BU = 0xffff8000,
+ MASK_LDX_HU = 0xffff8000,
+ MASK_LDX_WU = 0xffff8000,
+ MASK_PRELDX = 0xffff8000,
+ MASK_SC_Q = 0xffff8000,
+ MASK_LLACQ_W = 0xfffffc00,
+ MASK_SCREL_W = 0xfffffc00,
+ MASK_LLACQ_D = 0xfffffc00,
+ MASK_SCREL_D = 0xfffffc00,
+ MASK_AMCAS_B = 0xffff8000,
+ MASK_AMCAS_H = 0xffff8000,
+ MASK_AMCAS_W = 0xffff8000,
+ MASK_AMCAS_D = 0xffff8000,
+ MASK_AMCAS_DB_B = 0xffff8000,
+ MASK_AMCAS_DB_H = 0xffff8000,
+ MASK_AMCAS_DB_W = 0xffff8000,
+ MASK_AMCAS_DB_D = 0xffff8000,
+ MASK_AMSWAP_B = 0xffff8000,
+ MASK_AMSWAP_H = 0xffff8000,
+ MASK_AMADD_B = 0xffff8000,
+ MASK_AMADD_H = 0xffff8000,
+ MASK_AMSWAP_DB_B = 0xffff8000,
+ MASK_AMSWAP_DB_H = 0xffff8000,
+ MASK_AMADD_DB_B = 0xffff8000,
+ MASK_AMADD_DB_H = 0xffff8000,
+ MASK_AMSWAP_W = 0xffff8000,
+ MASK_AMSWAP_D = 0xffff8000,
+ MASK_AMADD_W = 0xffff8000,
+ MASK_AMADD_D = 0xffff8000,
+ MASK_AMAND_W = 0xffff8000,
+ MASK_AMAND_D = 0xffff8000,
+ MASK_AMOR_W = 0xffff8000,
+ MASK_AMOR_D = 0xffff8000,
+ MASK_AMXOR_W = 0xffff8000,
+ MASK_AMXOR_D = 0xffff8000,
+ MASK_AMMAX_W = 0xffff8000,
+ MASK_AMMAX_D = 0xffff8000,
+ MASK_AMMIN_W = 0xffff8000,
+ MASK_AMMIN_D = 0xffff8000,
+ MASK_AMMAX_WU = 0xffff8000,
+ MASK_AMMAX_DU = 0xffff8000,
+ MASK_AMMIN_WU = 0xffff8000,
+ MASK_AMMIN_DU = 0xffff8000,
+ MASK_AMSWAP_DB_W = 0xffff8000,
+ MASK_AMSWAP_DB_D = 0xffff8000,
+ MASK_AMADD_DB_W = 0xffff8000,
+ MASK_AMADD_DB_D = 0xffff8000,
+ MASK_AMAND_DB_W = 0xffff8000,
+ MASK_AMAND_DB_D = 0xffff8000,
+ MASK_AMOR_DB_W = 0xffff8000,
+ MASK_AMOR_DB_D = 0xffff8000,
+ MASK_AMXOR_DB_W = 0xffff8000,
+ MASK_AMXOR_DB_D = 0xffff8000,
+ MASK_AMMAX_DB_W = 0xffff8000,
+ MASK_AMMAX_DB_D = 0xffff8000,
+ MASK_AMMIN_DB_W = 0xffff8000,
+ MASK_AMMIN_DB_D = 0xffff8000,
+ MASK_AMMAX_DB_WU = 0xffff8000,
+ MASK_AMMAX_DB_DU = 0xffff8000,
+ MASK_AMMIN_DB_WU = 0xffff8000,
+ MASK_AMMIN_DB_DU = 0xffff8000,
+ MASK_DBAR = 0xffff8000,
+ MASK_IBAR = 0xffff8000,
+ MASK_LDGT_B = 0xffff8000,
+ MASK_LDGT_H = 0xffff8000,
+ MASK_LDGT_W = 0xffff8000,
+ MASK_LDGT_D = 0xffff8000,
+ MASK_LDLE_B = 0xffff8000,
+ MASK_LDLE_H = 0xffff8000,
+ MASK_LDLE_W = 0xffff8000,
+ MASK_LDLE_D = 0xffff8000,
+ MASK_STGT_B = 0xffff8000,
+ MASK_STGT_H = 0xffff8000,
+ MASK_STGT_W = 0xffff8000,
+ MASK_STGT_D = 0xffff8000,
+ MASK_STLE_B = 0xffff8000,
+ MASK_STLE_H = 0xffff8000,
+ MASK_STLE_W = 0xffff8000,
+ MASK_STLE_D = 0xffff8000,
+ MASK_VLD = 0xffc00000,
+ MASK_VST = 0xffc00000,
+ MASK_XVLD = 0xffc00000,
+ MASK_XVST = 0xffc00000,
+
+ /* loongarch single float load store insn mask */
+ MASK_FLD_S = 0xffc00000,
+ MASK_FST_S = 0xffc00000,
+ MASK_FLDX_S = 0xffff8000,
+ MASK_FSTX_S = 0xffff8000,
+ MASK_FLDGT_S = 0xffff8000,
+ MASK_FLDLE_S = 0xffff8000,
+ MASK_FSTGT_S = 0xffff8000,
+ MASK_FSTLE_S = 0xffff8000,
+
+ /* loongarch double float load store insn mask */
+ MASK_FLD_D = 0xffc00000,
+ MASK_FST_D = 0xffc00000,
+ MASK_FLDX_D = 0xffff8000,
+ MASK_FSTX_D = 0xffff8000,
+ MASK_FLDGT_D = 0xffff8000,
+ MASK_FLDLE_D = 0xffff8000,
+ MASK_FSTGT_D = 0xffff8000,
+ MASK_FSTLE_D = 0xffff8000,
+
+ /* loongarch float jmp insn mask */
+ MASK_BCEQZ = 0xfc000300,
+ MASK_BCNEZ = 0xfc000300,
+
+ /* loongarch jmp insn mask */
+ MASK_BEQZ = 0xfc000000,
+ MASK_BNEZ = 0xfc000000,
+ MASK_JIRL = 0xfc000000,
+ MASK_B = 0xfc000000,
+ MASK_BL = 0xfc000000,
+ MASK_BEQ = 0xfc000000,
+ MASK_BNE = 0xfc000000,
+ MASK_BLT = 0xfc000000,
+ MASK_BGE = 0xfc000000,
+ MASK_BLTU = 0xfc000000,
+ MASK_BGEU = 0xfc000000,
+};
+
+#define is_insn(insval,mask,funccode) (((insval) & (mask)) == funccode)
+
+#define is_data_process_insn(insval) \
+ ((is_insn(insval,MASK_CLO_W,OP_CLO_W)) || \
+ (is_insn(insval,MASK_CLZ_W,OP_CLZ_W)) || \
+ (is_insn(insval,MASK_CTO_W,OP_CTO_W)) || \
+ (is_insn(insval,MASK_CTZ_W,OP_CTZ_W)) || \
+ (is_insn(insval,MASK_CLO_D,OP_CLO_D)) || \
+ (is_insn(insval,MASK_CLZ_D,OP_CLZ_D)) || \
+ (is_insn(insval,MASK_CTO_D,OP_CTO_D)) || \
+ (is_insn(insval,MASK_CTZ_D,OP_CTZ_D)) || \
+ (is_insn(insval,MASK_REVB_2H,OP_REVB_2H)) || \
+ (is_insn(insval,MASK_REVB_4H,OP_REVB_4H)) || \
+ (is_insn(insval,MASK_REVB_2W,OP_REVB_2W)) || \
+ (is_insn(insval,MASK_REVH_2W,OP_REVH_2W)) || \
+ (is_insn(insval,MASK_REVH_D,OP_REVH_D)) || \
+ (is_insn(insval,MASK_BITREV_4B,OP_BITREV_4B)) || \
+ (is_insn(insval,MASK_BITREV_8B,OP_BITREV_8B)) || \
+ (is_insn(insval,MASK_BITREV_W,OP_BITREV_W)) || \
+ (is_insn(insval,MASK_BITREV_D,OP_BITREV_D)) || \
+ (is_insn(insval,MASK_EXT_W_H,OP_EXT_W_H)) || \
+ (is_insn(insval,MASK_EXT_W_B,OP_EXT_W_B)) || \
+ (is_insn(insval,MASK_CPUCFG,OP_CPUCFG)) || \
+ (is_insn(insval,MASK_ALSL_W,OP_ALSL_W)) || \
+ (is_insn(insval,MASK_ALSL_WU,OP_ALSL_WU)) || \
+ (is_insn(insval,MASK_BYTEPICK_W,OP_BYTEPICK_W)) || \
+ (is_insn(insval,MASK_BYTEPICK_D,OP_BYTEPICK_D)) || \
+ (is_insn(insval,MASK_ADD_W,OP_ADD_W)) || \
+ (is_insn(insval,MASK_ADD_D,OP_ADD_D)) || \
+ (is_insn(insval,MASK_SUB_W,OP_SUB_W)) || \
+ (is_insn(insval,MASK_SUB_D,OP_SUB_D)) || \
+ (is_insn(insval,MASK_SLT,OP_SLT)) || \
+ (is_insn(insval,MASK_SLTU,OP_SLTU)) || \
+ (is_insn(insval,MASK_MASKEQZ,OP_MASKEQZ)) || \
+ (is_insn(insval,MASK_MASKNEZ,OP_MASKNEZ)) || \
+ (is_insn(insval,MASK_NOR,OP_NOR)) || \
+ (is_insn(insval,MASK_AND,OP_AND)) || \
+ (is_insn(insval,MASK_OR,OP_OR)) || \
+ (is_insn(insval,MASK_XOR,OP_XOR)) || \
+ (is_insn(insval,MASK_ORN,OP_ORN)) || \
+ (is_insn(insval,MASK_ANDN,OP_ANDN)) || \
+ (is_insn(insval,MASK_SLL_W,OP_SLL_W)) || \
+ (is_insn(insval,MASK_SRL_W,OP_SRL_W)) || \
+ (is_insn(insval,MASK_SRA_W,OP_SRA_W)) || \
+ (is_insn(insval,MASK_SLL_D,OP_SLL_D)) || \
+ (is_insn(insval,MASK_SRL_D,OP_SRL_D)) || \
+ (is_insn(insval,MASK_SRA_D,OP_SRA_D)) || \
+ (is_insn(insval,MASK_ROTR_W,OP_ROTR_W)) || \
+ (is_insn(insval,MASK_ROTR_D,OP_ROTR_D)) || \
+ (is_insn(insval,MASK_MUL_W,OP_MUL_W)) || \
+ (is_insn(insval,MASK_MULH_W,OP_MULH_W)) || \
+ (is_insn(insval,MASK_MULH_WU,OP_MULH_WU)) || \
+ (is_insn(insval,MASK_MUL_D,OP_MUL_D)) || \
+ (is_insn(insval,MASK_MULH_D,OP_MULH_D)) || \
+ (is_insn(insval,MASK_MULH_DU,OP_MULH_DU)) || \
+ (is_insn(insval,MASK_MULW_D_W,OP_MULW_D_W)) || \
+ (is_insn(insval,MASK_MULW_D_WU,OP_MULW_D_WU)) || \
+ (is_insn(insval,MASK_DIV_W,OP_DIV_W)) || \
+ (is_insn(insval,MASK_MOD_W,OP_MOD_W)) || \
+ (is_insn(insval,MASK_DIV_WU,OP_DIV_WU)) || \
+ (is_insn(insval,MASK_MOD_WU,OP_MOD_WU)) || \
+ (is_insn(insval,MASK_DIV_D,OP_DIV_D)) || \
+ (is_insn(insval,MASK_MOD_D,OP_MOD_D)) || \
+ (is_insn(insval,MASK_DIV_DU,OP_DIV_DU)) || \
+ (is_insn(insval,MASK_MOD_DU,OP_MOD_DU)) || \
+ (is_insn(insval,MASK_CRC_W_B_W,OP_CRC_W_B_W)) || \
+ (is_insn(insval,MASK_CRC_W_H_W,OP_CRC_W_H_W)) || \
+ (is_insn(insval,MASK_CRC_W_W_W,OP_CRC_W_W_W)) || \
+ (is_insn(insval,MASK_CRC_W_D_W,OP_CRC_W_D_W)) || \
+ (is_insn(insval,MASK_CRCC_W_B_W,OP_CRCC_W_B_W)) || \
+ (is_insn(insval,MASK_CRCC_W_H_W,OP_CRCC_W_H_W)) || \
+ (is_insn(insval,MASK_CRCC_W_W_W,OP_CRCC_W_W_W)) || \
+ (is_insn(insval,MASK_CRCC_W_D_W,OP_CRCC_W_D_W)) || \
+ (is_insn(insval,MASK_ALSL_D,OP_ALSL_D)) || \
+ (is_insn(insval,MASK_SLLI_W,OP_SLLI_W)) || \
+ (is_insn(insval,MASK_SLLI_D,OP_SLLI_D)) || \
+ (is_insn(insval,MASK_SRLI_W,OP_SRLI_W)) || \
+ (is_insn(insval,MASK_SRLI_D,OP_SRLI_D)) || \
+ (is_insn(insval,MASK_SRAI_W,OP_SRAI_W)) || \
+ (is_insn(insval,MASK_SRAI_D,OP_SRAI_D)) || \
+ (is_insn(insval,MASK_ROTRI_W,OP_ROTRI_W)) || \
+ (is_insn(insval,MASK_ROTRI_D,OP_ROTRI_D)) || \
+ (is_insn(insval,MASK_BSTRINS_W,OP_BSTRINS_W)) || \
+ (is_insn(insval,MASK_BSTRPICK_W,OP_BSTRPICK_W)) || \
+ (is_insn(insval,MASK_BSTRINS_D,OP_BSTRINS_D)) || \
+ (is_insn(insval,MASK_BSTRPICK_D,OP_BSTRPICK_D)) || \
+ (is_insn(insval,MASK_MOVFR2GR_S,OP_MOVFR2GR_S)) || \
+ (is_insn(insval,MASK_MOVFRH2GR_S,OP_MOVFRH2GR_S)) || \
+ (is_insn(insval,MASK_MOVFCSR2GR,OP_MOVFCSR2GR)) || \
+ (is_insn(insval,MASK_MOVCF2GR,OP_MOVCF2GR)) || \
+ (is_insn(insval,MASK_MOVFR2GR_D,OP_MOVFR2GR_D)) || \
+ (is_insn(insval,MASK_SLTI,OP_SLTI)) || \
+ (is_insn(insval,MASK_SLTUI,OP_SLTUI)) || \
+ (is_insn(insval,MASK_ADDI_W,OP_ADDI_W)) || \
+ (is_insn(insval,MASK_ADDI_D,OP_ADDI_D)) || \
+ (is_insn(insval,MASK_LU52I_D,OP_LU52I_D)) || \
+ (is_insn(insval,MASK_ANDI,OP_ANDI)) || \
+ (is_insn(insval,MASK_ORI,OP_ORI)) || \
+ (is_insn(insval,MASK_XORI,OP_XORI)) || \
+ (is_insn(insval,MASK_ADDU16I_D,OP_ADDU16I_D)) || \
+ (is_insn(insval,MASK_LU12I_W,OP_LU12I_W)) || \
+ (is_insn(insval,MASK_LU32I_D,OP_LU32I_D)) || \
+ (is_insn(insval,MASK_PCADDI,OP_PCADDI)) || \
+ (is_insn(insval,MASK_PCALAU12I,OP_PCALAU12I)) || \
+ (is_insn(insval,MASK_PCADDU12I,OP_PCADDU12I)) || \
+ (is_insn(insval,MASK_PCADDU18I,OP_PCADDU18I)) || \
+ (is_insn(insval,MASK_LDDIR,OP_LDDIR)) || \
+ (is_insn(insval,MASK_LL_W,OP_LL_W)) || \
+ (is_insn(insval,MASK_LL_D,OP_LL_D)) || \
+ (is_insn(insval,MASK_LDPTR_W,OP_LDPTR_W)) || \
+ (is_insn(insval,MASK_LDPTR_D,OP_LDPTR_D)) || \
+ (is_insn(insval,MASK_LD_B,OP_LD_B)) || \
+ (is_insn(insval,MASK_LD_H,OP_LD_H)) || \
+ (is_insn(insval,MASK_LD_W,OP_LD_W)) || \
+ (is_insn(insval,MASK_LD_D,OP_LD_D)) || \
+ (is_insn(insval,MASK_LD_BU,OP_LD_BU)) || \
+ (is_insn(insval,MASK_LD_HU,OP_LD_HU)) || \
+ (is_insn(insval,MASK_LD_WU,OP_LD_WU)) || \
+ (is_insn(insval,MASK_LDX_B,OP_LDX_B)) || \
+ (is_insn(insval,MASK_LDX_H,OP_LDX_H)) || \
+ (is_insn(insval,MASK_LDX_W,OP_LDX_W)) || \
+ (is_insn(insval,MASK_LDX_D,OP_LDX_D)) || \
+ (is_insn(insval,MASK_LDX_BU,OP_LDX_BU)) || \
+ (is_insn(insval,MASK_LDX_HU,OP_LDX_HU)) || \
+ (is_insn(insval,MASK_LDX_WU,OP_LDX_WU)) || \
+ (is_insn(insval,MASK_VLD,OP_VLD)) || \
+ (is_insn(insval,MASK_XVLD,OP_XVLD)))
+
+#define is_read_time_insn(insval) \
+ ((is_insn(insval,MASK_RDTIMEL_W,OP_RDTIMEL_W)) || \
+ (is_insn(insval,MASK_RDTIMEH_W,OP_RDTIMEH_W)) || \
+ (is_insn(insval,MASK_RDTIME_D,OP_RDTIME_D)))
+
+#define is_syscall_insn(insval) \
+ (is_insn(insval,MASK_SYSCALL,OP_SYSCALL))
+
+#define is_float_insn(insval) \
+ ((is_insn(insval,MASK_FADD_S,OP_FADD_S)) || \
+ (is_insn(insval,MASK_SUB_S,OP_SUB_S)) || \
+ (is_insn(insval,MASK_FDIV_S,OP_FDIV_S)) || \
+ (is_insn(insval,MASK_FMAX_S,OP_FMAX_S)) || \
+ (is_insn(insval,MASK_FMIN_S,OP_FMIN_S)) || \
+ (is_insn(insval,MASK_FMAXA_S,OP_FMAXA_S)) || \
+ (is_insn(insval,MASK_FMINA_S,OP_FMINA_S)) || \
+ (is_insn(insval,MASK_FSCALEB_S,OP_FSCALEB_S)) || \
+ (is_insn(insval,MASK_FCOPYSIGN_S,OP_FCOPYSIGN_S)) || \
+ (is_insn(insval,MASK_FABS_S,OP_FABS_S)) || \
+ (is_insn(insval,MASK_FNEG_S,OP_FNEG_S)) || \
+ (is_insn(insval,MASK_FLOGB_S,OP_FLOGB_S)) || \
+ (is_insn(insval,MASK_FCLASS_S,OP_FCLASS_S)) || \
+ (is_insn(insval,MASK_FSQRT_S,OP_FSQRT_S)) || \
+ (is_insn(insval,MASK_FRECIP_S,OP_FRECIP_S)) || \
+ (is_insn(insval,MASK_FRSQRT_S,OP_FRSQRT_S)) || \
+ (is_insn(insval,MASK_FRECIPE_S,OP_FRECIPE_S)) || \
+ (is_insn(insval,MASK_FRSQRTE_S,OP_FRSQRTE_S)) || \
+ (is_insn(insval,MASK_FMOV_S,OP_FMOV_S)) || \
+ (is_insn(insval,MASK_MOVGR2FR_W,OP_MOVGR2FR_W)) || \
+ (is_insn(insval,MASK_MOVGR2FRH_W,OP_MOVGR2FRH_W)) || \
+ (is_insn(insval,MASK_MOVGR2FCSR,OP_MOVGR2FCSR)) || \
+ (is_insn(insval,MASK_MOVFR2CF,OP_MOVFR2CF)) || \
+ (is_insn(insval,MASK_MOVCF2FR,OP_MOVCF2FR)) || \
+ (is_insn(insval,MASK_MOVGR2CF,OP_MOVGR2CF)) || \
+ (is_insn(insval,MASK_FTINTRM_W_S,OP_FTINTRM_W_S)) || \
+ (is_insn(insval,MASK_FTINTRM_L_S,OP_FTINTRM_L_S)) || \
+ (is_insn(insval,MASK_FTINTRP_W_S,OP_FTINTRP_W_S)) || \
+ (is_insn(insval,MASK_FTINTRP_L_S,OP_FTINTRP_L_S)) || \
+ (is_insn(insval,MASK_FTINTRZ_W_S,OP_FTINTRZ_W_S)) || \
+ (is_insn(insval,MASK_FTINTRZ_L_S,OP_FTINTRZ_L_S)) || \
+ (is_insn(insval,MASK_FTINTRNE_W_S,OP_FTINTRNE_W_S)) || \
+ (is_insn(insval,MASK_FTINTRNE_L_S,OP_FTINTRNE_L_S)) || \
+ (is_insn(insval,MASK_FTINT_W_S,OP_FTINT_W_S)) || \
+ (is_insn(insval,MASK_FTINT_L_S,OP_FTINT_L_S)) || \
+ (is_insn(insval,MASK_FFINT_S_W,OP_FFINT_S_W)) || \
+ (is_insn(insval,MASK_FFINT_S_L,OP_FFINT_S_L)) || \
+ (is_insn(insval,MASK_FRINT_S,OP_FRINT_S)) || \
+ (is_insn(insval,MASK_FADD_D,OP_FADD_D)) || \
+ (is_insn(insval,MASK_FSUB_D,OP_FSUB_D)) || \
+ (is_insn(insval,MASK_FMUL_D,OP_FMUL_D)) || \
+ (is_insn(insval,MASK_FDIV_D,OP_FDIV_D)) || \
+ (is_insn(insval,MASK_FMAX_D,OP_FMAX_D)) || \
+ (is_insn(insval,MASK_FMIN_D,OP_FMIN_D)) || \
+ (is_insn(insval,MASK_FMAXA_D,OP_FMAXA_D)) || \
+ (is_insn(insval,MASK_FMINA_D,OP_FMINA_D)) || \
+ (is_insn(insval,MASK_FSCALEB_D,OP_FSCALEB_D)) || \
+ (is_insn(insval,MASK_FCOPYSIGN_D,OP_FCOPYSIGN_D)) || \
+ (is_insn(insval,MASK_FABS_D,OP_FABS_D)) || \
+ (is_insn(insval,MASK_FNEG_D,OP_FNEG_D)) || \
+ (is_insn(insval,MASK_FLOGB_D,OP_FLOGB_D)) || \
+ (is_insn(insval,MASK_FCLASS_D,OP_FCLASS_D)) || \
+ (is_insn(insval,MASK_FSQRT_D,OP_FSQRT_D)) || \
+ (is_insn(insval,MASK_FRECIP_D,OP_FRECIP_D)) || \
+ (is_insn(insval,MASK_FRSQRT_D,OP_FRSQRT_D)) || \
+ (is_insn(insval,MASK_FRECIPE_D,OP_FRECIPE_D)) || \
+ (is_insn(insval,MASK_FRSQRTE_D,OP_FRSQRTE_D)) || \
+ (is_insn(insval,MASK_FMOV_D,OP_FMOV_D)) || \
+ (is_insn(insval,MASK_MOVGR2FR_D,OP_MOVGR2FR_D)) || \
+ (is_insn(insval,MASK_FCVT_S_D,OP_FCVT_S_D)) || \
+ (is_insn(insval,MASK_FCVT_D_S,OP_FCVT_D_S)) || \
+ (is_insn(insval,MASK_FTINTRM_W_D,OP_FTINTRM_W_D)) || \
+ (is_insn(insval,MASK_FTINTRM_L_D,OP_FTINTRM_L_D)) || \
+ (is_insn(insval,MASK_FTINTRP_W_D,OP_FTINTRP_W_D)) || \
+ (is_insn(insval,MASK_FTINTRP_L_D,OP_FTINTRP_L_D)) || \
+ (is_insn(insval,MASK_FTINTRZ_W_D,OP_FTINTRZ_W_D)) || \
+ (is_insn(insval,MASK_FTINTRZ_L_D,OP_FTINTRZ_L_D)) || \
+ (is_insn(insval,MASK_FTINTRNE_W_D,OP_FTINTRNE_W_D)) || \
+ (is_insn(insval,MASK_FTINTRNE_L_D,OP_FTINTRNE_L_D)) || \
+ (is_insn(insval,MASK_FTINT_W_D,OP_FTINT_W_D)) || \
+ (is_insn(insval,MASK_FTINT_L_D,OP_FTINT_L_D)) || \
+ (is_insn(insval,MASK_FFINT_D_W,OP_FFINT_D_W)) || \
+ (is_insn(insval,MASK_FFINT_D_L,OP_FFINT_D_L)) || \
+ (is_insn(insval,MASK_FRINT_D,OP_FRINT_D)) || \
+ (is_insn(insval,MASK_FMADD_S,OP_FMADD_S)) || \
+ (is_insn(insval,MASK_FMSUB_S,OP_FMSUB_S)) || \
+ (is_insn(insval,MASK_FNMADD_S,OP_FNMADD_S)) || \
+ (is_insn(insval,MASK_FNMSUB_S,OP_FNMSUB_S)) || \
+ (is_insn(insval,MASK_FMADD_D,OP_FMADD_D)) || \
+ (is_insn(insval,MASK_FMSUB_D,OP_FMSUB_D)) || \
+ (is_insn(insval,MASK_FNMADD_D,OP_FNMADD_D)) || \
+ (is_insn(insval,MASK_FNMSUB_D,OP_FNMSUB_D)) || \
+ (is_insn(insval,MASK_FLD_S,OP_FLD_S)) || \
+ (is_insn(insval,MASK_FLD_D,OP_FLD_D)) || \
+ (is_insn(insval,MASK_FLDX_S,OP_FLDX_S)) || \
+ (is_insn(insval,MASK_FLDX_D,OP_FLDX_D)))
+
+#define is_mov2cf_insn(insval) \
+ ((is_insn(insval,MASK_MOVFR2CF,OP_MOVFR2CF)) || \
+ (is_insn(insval,MASK_MOVGR2CF,OP_MOVGR2CF)))
+
+#define is_movgr2fcsr_insn(insval) \
+ (is_insn(insval,MASK_MOVGR2FCSR,OP_MOVGR2FCSR))
+
+
+#define is_stb_insn(insval) (is_insn(insval,MASK_ST_B,OP_ST_B))
+#define is_sth_insn(insval) (is_insn(insval,MASK_ST_H,OP_ST_H))
+#define is_stw_insn(insval) (is_insn(insval,MASK_ST_W,OP_ST_W))
+#define is_std_insn(insval) (is_insn(insval,MASK_ST_D,OP_ST_D))
+#define is_stptrw_insn(insval) (is_insn(insval,MASK_STPTR_W,OP_STPTR_W))
+#define is_stptrd_insn(insval) (is_insn(insval,MASK_STPTR_D,OP_STPTR_D))
+#define is_scw_insn(insval) (is_insn(insval,MASK_SC_W,OP_SC_W))
+#define is_scd_insn(insval) (is_insn(insval,MASK_SC_D,OP_SC_D))
+#define is_fsts_insn(insval) (is_insn(insval,MASK_FST_S,OP_FST_S))
+#define is_fstd_insn(insval) (is_insn(insval,MASK_FST_D,OP_FST_D))
+#define is_fstxs_insn(insval) (is_insn(insval,MASK_FSTX_S,OP_FSTX_S))
+#define is_fstxd_insn(insval) (is_insn(insval,MASK_FSTX_D,OP_FSTX_D))
+#define is_stxb_insn(insval) (is_insn(insval,MASK_STX_B,OP_STX_B))
+#define is_stxh_insn(insval) (is_insn(insval,MASK_STX_H,OP_STX_H))
+#define is_stxw_insn(insval) (is_insn(insval,MASK_STX_W,OP_STX_W))
+#define is_stxd_insn(insval) (is_insn(insval,MASK_STX_D,OP_STX_D))
+#define is_vst_insn(insval) (is_insn(insval,MASK_VST,OP_VST))
+#define is_xvst_insn(insval) (is_insn(insval,MASK_XVST,OP_XVST))
+
+#define is_store_insn(insval) \
+ ((is_stb_insn(insval)) || \
+ (is_sth_insn(insval)) || \
+ (is_stw_insn(insval)) || \
+ (is_std_insn(insval)) || \
+ (is_stptrw_insn(insval)) || \
+ (is_stptrd_insn(insval)) || \
+ (is_scw_insn(insval)) || \
+ (is_scd_insn(insval)) || \
+ (is_fsts_insn(insval)) || \
+ (is_fstd_insn(insval)) || \
+ (is_stxb_insn(insval)) || \
+ (is_stxh_insn(insval)) || \
+ (is_stxw_insn(insval)) || \
+ (is_stxd_insn(insval)) || \
+ (is_vst_insn(insval)) || \
+ (is_xvst_insn(insval)))
+
+#define is_am_insn(insval) \
+ ((is_insn(insval,MASK_AMSWAP_W,OP_AMSWAP_W)) || \
+ (is_insn(insval,MASK_AMSWAP_D,OP_AMSWAP_D)) || \
+ (is_insn(insval,MASK_AMADD_W,OP_AMADD_W)) || \
+ (is_insn(insval,MASK_AMADD_D,OP_AMADD_D)) || \
+ (is_insn(insval,MASK_AMAND_W,OP_AMAND_W)) || \
+ (is_insn(insval,MASK_AMAND_D,OP_AMAND_D)) || \
+ (is_insn(insval,MASK_AMOR_W,OP_AMOR_W)) || \
+ (is_insn(insval,MASK_AMOR_D,OP_AMOR_D)) || \
+ (is_insn(insval,MASK_AMXOR_W,OP_AMXOR_W)) || \
+ (is_insn(insval,MASK_AMXOR_D,OP_AMXOR_D)) || \
+ (is_insn(insval,MASK_AMMAX_W,OP_AMMAX_W)) || \
+ (is_insn(insval,MASK_AMMAX_D,OP_AMMAX_D)) || \
+ (is_insn(insval,MASK_AMMIN_W,OP_AMMIN_W)) || \
+ (is_insn(insval,MASK_AMMIN_D,OP_AMMIN_D)) || \
+ (is_insn(insval,MASK_AMMAX_WU,OP_AMMAX_WU)) || \
+ (is_insn(insval,MASK_AMMAX_DU,OP_AMMAX_DU)) || \
+ (is_insn(insval,MASK_AMMIN_WU,OP_AMMIN_WU)) || \
+ (is_insn(insval,MASK_AMMIN_DU,OP_AMMIN_DU)) || \
+ (is_insn(insval,MASK_AMSWAP_DB_W,OP_AMSWAP_DB_W)) || \
+ (is_insn(insval,MASK_AMSWAP_DB_D,OP_AMSWAP_DB_D)) || \
+ (is_insn(insval,MASK_AMADD_DB_W,OP_AMADD_DB_W)) || \
+ (is_insn(insval,MASK_AMADD_DB_D,OP_AMADD_DB_D)) || \
+ (is_insn(insval,MASK_AMAND_DB_W,OP_AMAND_DB_W)) || \
+ (is_insn(insval,MASK_AMAND_DB_D,OP_AMAND_DB_D)) || \
+ (is_insn(insval,MASK_AMOR_DB_W,OP_AMOR_DB_W)) || \
+ (is_insn(insval,MASK_AMOR_DB_D,OP_AMOR_DB_D)) || \
+ (is_insn(insval,MASK_AMXOR_DB_W,OP_AMXOR_DB_W)) || \
+ (is_insn(insval,MASK_AMXOR_DB_D,OP_AMXOR_DB_D)) || \
+ (is_insn(insval,MASK_AMMAX_DB_W,OP_AMMAX_DB_W)) || \
+ (is_insn(insval,MASK_AMMAX_DB_D,OP_AMMAX_DB_D)) || \
+ (is_insn(insval,MASK_AMMIN_DB_W,OP_AMMIN_DB_W)) || \
+ (is_insn(insval,MASK_AMMIN_DB_D,OP_AMMIN_DB_D)) || \
+ (is_insn(insval,MASK_AMMAX_DB_WU,OP_AMMAX_DB_WU)) || \
+ (is_insn(insval,MASK_AMMAX_DB_DU,OP_AMMAX_DB_DU)) || \
+ (is_insn(insval,MASK_AMMIN_DB_WU,OP_AMMIN_DB_WU)) || \
+ (is_insn(insval,MASK_AMMIN_DB_DU,OP_AMMIN_DB_DU)))
+
+
+#define is_cond_load_insn(insval) \
+ ((is_insn(insval,MASK_LDGT_B,OP_LDGT_B)) || \
+ (is_insn(insval,MASK_LDGT_H,OP_LDGT_H)) || \
+ (is_insn(insval,MASK_LDGT_W,OP_LDGT_W)) || \
+ (is_insn(insval,MASK_LDGT_D,OP_LDGT_D)) || \
+ (is_insn(insval,MASK_LDLE_B,OP_LDLE_B)) || \
+ (is_insn(insval,MASK_LDLE_H,OP_LDLE_H)) || \
+ (is_insn(insval,MASK_LDLE_W,OP_LDLE_W)) || \
+ (is_insn(insval,MASK_LDLE_D,OP_LDLE_D)) || \
+ (is_insn(insval,MASK_FLDGT_S,OP_FLDGT_S)) || \
+ (is_insn(insval,MASK_FLDLE_S,OP_FLDLE_S)) || \
+ (is_insn(insval,MASK_FLDGT_D,OP_FLDGT_D)) || \
+ (is_insn(insval,MASK_FLDLE_D,OP_FLDLE_D)))
+
+#define is_cond_store_insn(insval) \
+ ((is_insn(insval,MASK_STGT_B,OP_STGT_B)) || \
+ (is_insn(insval,MASK_STGT_H,OP_STGT_H)) || \
+ (is_insn(insval,MASK_STGT_W,OP_STGT_W)) || \
+ (is_insn(insval,MASK_STGT_D,OP_STGT_D)) || \
+ (is_insn(insval,MASK_STLE_B,OP_STLE_B)) || \
+ (is_insn(insval,MASK_STLE_H,OP_STLE_H)) || \
+ (is_insn(insval,MASK_STLE_W,OP_STLE_W)) || \
+ (is_insn(insval,MASK_STLE_D,OP_STLE_D)) || \
+ (is_insn(insval,MASK_FSTGT_S,OP_FSTGT_S)) || \
+ (is_insn(insval,MASK_FSTLE_S,OP_FSTLE_S)) || \
+ (is_insn(insval,MASK_FSTGT_D,OP_FSTGT_D)) || \
+ (is_insn(insval,MASK_FSTLE_D,OP_FSTLE_D)))
+
+#define is_ldgt_insn(insval) \
+ ((is_insn(insval,MASK_LDGT_B,OP_LDGT_B)) || \
+ (is_insn(insval,MASK_LDGT_H,OP_LDGT_H)) || \
+ (is_insn(insval,MASK_LDGT_W,OP_LDGT_W)) || \
+ (is_insn(insval,MASK_LDGT_D,OP_LDGT_D)))
+
+#define is_ldle_insn(insval) \
+ ((is_insn(insval,MASK_LDLE_B,OP_LDLE_B)) || \
+ (is_insn(insval,MASK_LDLE_H,OP_LDLE_H)) || \
+ (is_insn(insval,MASK_LDLE_W,OP_LDLE_W)) || \
+ (is_insn(insval,MASK_LDLE_D,OP_LDLE_D)))
+
+#define is_fldgt_insn(insval) \
+ ((is_insn(insval,MASK_FLDGT_S,OP_FLDGT_S)) || \
+ (is_insn(insval,MASK_FLDGT_D,OP_FLDGT_D)))
+
+#define is_fldle_insn(insval) \
+ ((is_insn(insval,MASK_FLDLE_S,OP_FLDLE_S)) || \
+ (is_insn(insval,MASK_FLDLE_D,OP_FLDLE_D)))
+
+
+#define is_stgt_insn(insval) \
+ ((is_insn(insval,MASK_STGT_B,OP_STGT_B)) || \
+ (is_insn(insval,MASK_STGT_H,OP_STGT_H)) || \
+ (is_insn(insval,MASK_STGT_W,OP_STGT_W)) || \
+ (is_insn(insval,MASK_STGT_D,OP_STGT_D)))
+
+#define is_stle_insn(insval) \
+ ((is_insn(insval,MASK_STLE_B,OP_STLE_B)) || \
+ (is_insn(insval,MASK_STLE_H,OP_STLE_H)) || \
+ (is_insn(insval,MASK_STLE_W,OP_STLE_W)) || \
+ (is_insn(insval,MASK_STLE_D,OP_STLE_D)))
+
+#define is_fstgt_insn(insval) \
+ ((is_insn(insval,MASK_FSTGT_S,OP_FSTGT_S)) || \
+ (is_insn(insval,MASK_FSTGT_D,OP_FSTGT_D)))
+
+#define is_fstle_insn(insval) \
+ ((is_insn(insval,MASK_FSTLE_S,OP_FSTLE_S)) || \
+ (is_insn(insval,MASK_FSTLE_D,OP_FSTLE_D)))
+
+#define is_jirl_insn(insval) (is_insn(insval,MASK_JIRL,OP_JIRL))
+#define is_bl_insn(insval) (is_insn(insval,MASK_BL,OP_BL))
+
+#define is_jump_insn(insval) \
+ ((is_insn(insval,MASK_BEQZ,OP_BEQZ)) || \
+ (is_insn(insval,MASK_BNEZ,OP_BNEZ)) || \
+ (is_insn(insval,MASK_JIRL,OP_JIRL)) || \
+ (is_insn(insval,MASK_B,OP_B)) || \
+ (is_insn(insval,MASK_BL,OP_BL)) || \
+ (is_insn(insval,MASK_BEQ,OP_BEQ)) || \
+ (is_insn(insval,MASK_BNE,OP_BNE)) || \
+ (is_insn(insval,MASK_BLT,OP_BLT)) || \
+ (is_insn(insval,MASK_BGE,OP_BGE)) || \
+ (is_insn(insval,MASK_BLTU,OP_BLTU)) || \
+ (is_insn(insval,MASK_BGEU,OP_BGEU)))
+
+#define is_special_insn(insval) \
+ ((is_insn(insval,MASK_CACOP,OP_CACOP)) || \
+ (is_insn(insval,MASK_TLBCLR,OP_TLBCLR)) || \
+ (is_insn(insval,MASK_TLBFLUSH,OP_TLBFLUSH)) || \
+ (is_insn(insval,MASK_TLBWR,OP_TLBWR)) || \
+ (is_insn(insval,MASK_TLBFILL,OP_TLBFILL)) || \
+ (is_insn(insval,MASK_IDLE,OP_IDLE)) || \
+ (is_insn(insval,MASK_INVTLB,OP_INVTLB)) || \
+ (is_insn(insval,MASK_PRELD,OP_PRELD)) || \
+ (is_insn(insval,MASK_PRELDX,OP_PRELDX)) || \
+ (is_insn(insval,MASK_DBAR,OP_DBAR)) || \
+ (is_insn(insval,MASK_IBAR,OP_IBAR)) || \
+ (is_fcmpcond_insn(insval)))
+
+#define is_fcmpcond_insn(insval) \
+ ((is_insn(insval,MASK_FCMP_CAF_S,OP_FCMP_CAF_S)) || \
+ (is_insn(insval,MASK_FCMP_SAF_S,OP_FCMP_SAF_S)) || \
+ (is_insn(insval,MASK_FCMP_CLT_S,OP_FCMP_CLT_S)) || \
+ (is_insn(insval,MASK_FCMP_SLT_S,OP_FCMP_SLT_S)) || \
+ (is_insn(insval,MASK_FCMP_SGT_S,OP_FCMP_SGT_S)) || \
+ (is_insn(insval,MASK_FCMP_CEQ_S,OP_FCMP_CEQ_S)) || \
+ (is_insn(insval,MASK_FCMP_SEQ_S,OP_FCMP_SEQ_S)) || \
+ (is_insn(insval,MASK_FCMP_CLE_S,OP_FCMP_CLE_S)) || \
+ (is_insn(insval,MASK_FCMP_SLE_S,OP_FCMP_SLE_S)) || \
+ (is_insn(insval,MASK_FCMP_SGE_S,OP_FCMP_SGE_S)) || \
+ (is_insn(insval,MASK_FCMP_CUN_S,OP_FCMP_CUN_S)) || \
+ (is_insn(insval,MASK_FCMP_SUN_S,OP_FCMP_SUN_S)) || \
+ (is_insn(insval,MASK_FCMP_CULT_S,OP_FCMP_CULT_S)) || \
+ (is_insn(insval,MASK_FCMP_CUGT_S,OP_FCMP_CUGT_S)) || \
+ (is_insn(insval,MASK_FCMP_SULT_S,OP_FCMP_SULT_S)) || \
+ (is_insn(insval,MASK_FCMP_CUEQ_S,OP_FCMP_CUEQ_S)) || \
+ (is_insn(insval,MASK_FCMP_SUEQ_S,OP_FCMP_SUEQ_S)) || \
+ (is_insn(insval,MASK_FCMP_CULE_S,OP_FCMP_CULE_S)) || \
+ (is_insn(insval,MASK_FCMP_CUGE_S,OP_FCMP_CUGE_S)) || \
+ (is_insn(insval,MASK_FCMP_SULE_S,OP_FCMP_SULE_S)) || \
+ (is_insn(insval,MASK_FCMP_CNE_S,OP_FCMP_CNE_S)) || \
+ (is_insn(insval,MASK_FCMP_SNE_S,OP_FCMP_SNE_S)) || \
+ (is_insn(insval,MASK_FCMP_COR_S,OP_FCMP_COR_S)) || \
+ (is_insn(insval,MASK_FCMP_SOR_S,OP_FCMP_SOR_S)) || \
+ (is_insn(insval,MASK_FCMP_CUNE_S,OP_FCMP_CUNE_S)) || \
+ (is_insn(insval,MASK_FCMP_SUNE_S,OP_FCMP_SUNE_S)) || \
+ (is_insn(insval,MASK_FCMP_CAF_D,OP_FCMP_CAF_D)) || \
+ (is_insn(insval,MASK_FCMP_SAF_D,OP_FCMP_SAF_D)) || \
+ (is_insn(insval,MASK_FCMP_CLT_D,OP_FCMP_CLT_D)) || \
+ (is_insn(insval,MASK_FCMP_SLT_D,OP_FCMP_SLT_D)) || \
+ (is_insn(insval,MASK_FCMP_SGT_D,OP_FCMP_SGT_D)) || \
+ (is_insn(insval,MASK_FCMP_CEQ_D,OP_FCMP_CEQ_D)) || \
+ (is_insn(insval,MASK_FCMP_SEQ_D,OP_FCMP_SEQ_D)) || \
+ (is_insn(insval,MASK_FCMP_CLE_D,OP_FCMP_CLE_D)) || \
+ (is_insn(insval,MASK_FCMP_SLE_D,OP_FCMP_SLE_D)) || \
+ (is_insn(insval,MASK_FCMP_SGE_D,OP_FCMP_SGE_D)) || \
+ (is_insn(insval,MASK_FCMP_CUN_D,OP_FCMP_CUN_D)) || \
+ (is_insn(insval,MASK_FCMP_SUN_D,OP_FCMP_SUN_D)) || \
+ (is_insn(insval,MASK_FCMP_CULT_D,OP_FCMP_CULT_D)) || \
+ (is_insn(insval,MASK_FCMP_CUGT_D,OP_FCMP_CUGT_D)) || \
+ (is_insn(insval,MASK_FCMP_SULT_D,OP_FCMP_SULT_D)) || \
+ (is_insn(insval,MASK_FCMP_CUEQ_D,OP_FCMP_CUEQ_D)) || \
+ (is_insn(insval,MASK_FCMP_SUEQ_D,OP_FCMP_SUEQ_D)) || \
+ (is_insn(insval,MASK_FCMP_CULE_D,OP_FCMP_CULE_D)) || \
+ (is_insn(insval,MASK_FCMP_CUGE_D,OP_FCMP_CUGE_D)) || \
+ (is_insn(insval,MASK_FCMP_SULE_D,OP_FCMP_SULE_D)) || \
+ (is_insn(insval,MASK_FCMP_CNE_D,OP_FCMP_CNE_D)) || \
+ (is_insn(insval,MASK_FCMP_SNE_D,OP_FCMP_SNE_D)) || \
+ (is_insn(insval,MASK_FCMP_COR_D,OP_FCMP_COR_D)) || \
+ (is_insn(insval,MASK_FCMP_SOR_D,OP_FCMP_SOR_D)) || \
+ (is_insn(insval,MASK_FCMP_CUNE_D,OP_FCMP_CUNE_D)) || \
+ (is_insn(insval,MASK_FCMP_SUNE_D,OP_FCMP_SUNE_D)))
+
+#endif /* ARCH_LOONGARCH_INSN_H */
--
2.38.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support
2024-11-13 9:53 [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support Hui Li
2024-11-13 9:53 ` [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record Hui Li
@ 2024-11-13 9:53 ` Hui Li
2024-11-13 12:41 ` Guinevere Larsen
2024-11-13 9:53 ` [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay Hui Li
2024-11-13 9:53 ` [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc Hui Li
3 siblings, 1 reply; 13+ messages in thread
From: Hui Li @ 2024-11-13 9:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Tiezhu Yang
GDB provides a special process record and replay target that can
record a log of the process execution, and replay it later with
both forward and reverse execution commands. This patch adds the
basic support of process record and replay on LoongArch, it allows
users to debug basic LoongArch instructions and provides reverse
debugging support.
Here is a simple example on LoongArch:
$ cat test.c
int a = 0;
int main()
{
a = 1;
a = 2;
return 0;
}
$ gdb test
...
(gdb) start
...
Temporary breakpoint 1, main () at test.c:4
4 a = 1;
(gdb) record
(gdb) p a
$1 = 0
(gdb) n
5 a = 2;
(gdb) n
6 return 0;
(gdb) p a
$2 = 2
(gdb) rn
5 a = 2;
(gdb) rn
Reached end of recorded history; stopping.
Backward execution from here not possible.
main () at test.c:4
4 a = 1;
(gdb) p a
$3 = 0
(gdb) record stop
Process record is stopped and all execution logs are deleted.
(gdb) c
Continuing.
[Inferior 1 (process 129178) exited normally]
Signed-off-by: Hui Li <lihui@loongson.cn>
---
gdb/configure.tgt | 2 +-
gdb/loongarch-linux-tdep.c | 3 +
gdb/loongarch-tdep.c | 592 +++++++++++++++++++++++++++++++++++++
gdb/loongarch-tdep.h | 3 +
gdb/testsuite/lib/gdb.exp | 2 +
5 files changed, 601 insertions(+), 1 deletion(-)
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 62df71b13fa..2d78c1182fa 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -363,7 +363,7 @@ lm32-*-*)
loongarch*-*-linux*)
# Target: LoongArch running Linux
gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
- linux-tdep.o solib-svr4.o"
+ linux-tdep.o solib-svr4.o linux-record.o"
;;
m32c-*-*)
diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
index 71578060303..86e7ed8a0bc 100644
--- a/gdb/loongarch-linux-tdep.c
+++ b/gdb/loongarch-linux-tdep.c
@@ -602,6 +602,9 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Get the syscall number from the arch's register. */
set_gdbarch_get_syscall_number (gdbarch, loongarch_linux_get_syscall_number);
+
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, loongarch_process_record);
}
/* Initialize LoongArch Linux target support. */
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index c50dd7f4b78..cf72c48b573 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -18,12 +18,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
+#include "arch/loongarch-insn.h"
#include "dwarf2/frame.h"
#include "elf-bfd.h"
#include "extract-store-integer.h"
#include "frame-unwind.h"
#include "gdbcore.h"
+#include "linux-record.h"
#include "loongarch-tdep.h"
+#include "record.h"
+#include "record-full.h"
#include "reggroups.h"
#include "target.h"
#include "target-descriptions.h"
@@ -1889,6 +1893,594 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return gdbarch;
}
+/* LoongArch process record-replay related structures, defines etc. */
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct loongarch_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct loongarch_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* LoongArch record/replay structures and enumerations. */
+
+struct loongarch_mem_r
+{
+ uint64_t len; /* Record length. */
+ uint64_t addr; /* Memory address. */
+};
+
+enum loongarch_record_result
+{
+ LOONGARCH_RECORD_SUCCESS,
+ LOONGARCH_RECORD_UNSUPPORTED,
+ LOONGARCH_RECORD_UNKNOWN
+};
+
+struct loongarch_insn_record
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Addr of insn to be recorded. */
+ uint32_t insn; /* Insn to be recorded. */
+ uint32_t mem_rec_count; /* Count of memory records. */
+ uint32_t reg_rec_count; /* Count of register records. */
+ uint32_t *regs; /* Registers to be recorded. */
+ struct loongarch_mem_r *loongarch_mems; /* Memory location to be recorded. */
+};
+
+/* Record handler for data processing instructions. */
+
+static unsigned int
+loongarch_record_data_proc_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int rd;
+ uint32_t record_buf[1];
+ rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ record_buf[0] = rd;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for read time instructions. */
+
+static unsigned int
+loongarch_record_read_time_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int rd, rj;
+ uint32_t record_buf[2];
+ rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ rj = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ record_buf[0] = rd;
+ record_buf[1] = rj;
+ loongarch_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for jump instructions. */
+
+static unsigned int
+loongarch_record_jump_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ if (is_jirl_insn (loongarch_insn_r->insn))
+ {
+ int rd;
+ uint32_t record_buf[1];
+ rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ record_buf[0] = rd;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+ }
+ else if(is_bl_insn (loongarch_insn_r->insn))
+ {
+ uint32_t record_buf[1];
+ record_buf[0] = LOONGARCH_RA_REGNUM;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+ }
+
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for float data processing instructions. */
+
+static unsigned int
+loongarch_record_float_data_proc_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int fd;
+ uint32_t record_buf[1];
+ fd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
+ + LOONGARCH_FIRST_FP_REGNUM;
+ record_buf[0] = fd;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for fcsr processing instructions. */
+
+static unsigned int
+loongarch_record_fcsr_proc_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int fcsr;
+ uint32_t record_buf[1];
+ fcsr = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
+ + LOONGARCH_FCSR_REGNUM;
+ record_buf[0] = fcsr;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for condition flag register processing instructions. */
+
+static unsigned int
+loongarch_record_fcc_proc_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int cd, imm3_4;
+ uint32_t record_buf[1];
+ cd = loongarch_decode_imm ("0:3", loongarch_insn_r->insn, 0);
+ imm3_4 = loongarch_decode_imm ("3:2", loongarch_insn_r->insn, 0);
+ if (imm3_4 != 0)
+ return LOONGARCH_RECORD_UNSUPPORTED;
+
+ record_buf[0] = cd;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for float instructions. */
+
+static unsigned int
+loongarch_record_float_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ if (is_movgr2fcsr_insn (loongarch_insn_r->insn))
+ return loongarch_record_fcsr_proc_insn (loongarch_insn_r);
+ else if (is_mov2cf_insn (loongarch_insn_r->insn))
+ return loongarch_record_fcc_proc_insn (loongarch_insn_r);
+ else
+ return loongarch_record_float_data_proc_insn (loongarch_insn_r);
+}
+
+/* Record handler for store instructions. */
+
+static unsigned int
+loongarch_record_store_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ enum store_types
+ {
+ STB, STH, STW, STD, STXB, STXH, STXW, STXD, STPTRW, STPTRD,
+ SCW, SCD, FSTS, FSTD, FSTXS, FSTXD, VST, XVST, NOT_STORE
+ };
+ int store_type;
+ uint64_t record_buf_mem[2];
+ store_type = is_stb_insn (loongarch_insn_r->insn) ? STB :
+ is_sth_insn (loongarch_insn_r->insn) ? STH :
+ is_stw_insn (loongarch_insn_r->insn) ? STW :
+ is_std_insn (loongarch_insn_r->insn) ? STD :
+ is_stxb_insn (loongarch_insn_r->insn) ? STXB :
+ is_stxh_insn (loongarch_insn_r->insn) ? STXH :
+ is_stxw_insn (loongarch_insn_r->insn) ? STXW :
+ is_stxd_insn (loongarch_insn_r->insn) ? STXD :
+ is_stptrw_insn (loongarch_insn_r->insn) ? STPTRW :
+ is_stptrd_insn (loongarch_insn_r->insn) ? STPTRD :
+ is_scw_insn (loongarch_insn_r->insn) ? SCW :
+ is_scd_insn (loongarch_insn_r->insn) ? SCD :
+ is_fsts_insn (loongarch_insn_r->insn) ? FSTS :
+ is_fstd_insn (loongarch_insn_r->insn) ? FSTD :
+ is_fstxs_insn (loongarch_insn_r->insn) ? FSTXS :
+ is_fstxd_insn (loongarch_insn_r->insn) ? FSTXD :
+ is_vst_insn (loongarch_insn_r->insn) ? VST :
+ is_xvst_insn (loongarch_insn_r->insn) ? XVST :
+ NOT_STORE;
+
+ if (store_type == STB || store_type == STH || store_type == STW
+ || store_type == STD || store_type == FSTS || store_type == FSTD
+ || store_type == VST || store_type == XVST)
+ {
+ int rj_num;
+ int data_size;
+ int imm;
+ uint64_t rj_val;
+ uint64_t address;
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ imm = loongarch_decode_imm ("10:12", loongarch_insn_r->insn, 1);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
+ address = rj_val + imm;
+ switch (store_type)
+ {
+ case STB:
+ data_size = 1;
+ break;
+ case STH:
+ data_size = 2;
+ break;
+ case STW:
+ case FSTS:
+ data_size = 4;
+ break;
+ case STD:
+ case FSTD:
+ data_size = 8;
+ break;
+ case VST:
+ data_size = 16;
+ break;
+ case XVST:
+ data_size = 32;
+ break;
+ default:
+ data_size = 0;
+ break;
+ }
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = address;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems,
+ loongarch_insn_r->mem_rec_count, record_buf_mem);
+ return LOONGARCH_RECORD_SUCCESS;
+ }
+ else if (store_type == STXB || store_type == STXH || store_type == STXW
+ || store_type == STXD || store_type == FSTXS || store_type == FSTXD)
+ {
+ int data_size;
+ int rj_num, rk_num;
+ uint64_t rj_val,rk_val;
+ uint64_t address;
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
+ address = rj_val + rk_val;
+ switch (store_type)
+ {
+ case STXB:
+ data_size = 1;
+ break;
+ case STXH:
+ data_size = 2;
+ break;
+ case STXW:
+ case FSTXS:
+ data_size = 4;
+ break;
+ case STXD:
+ case FSTXD:
+ data_size = 8;
+ break;
+ default:
+ data_size = 0;
+ break;
+ }
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = address;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems,
+ loongarch_insn_r->mem_rec_count, record_buf_mem);
+
+ return LOONGARCH_RECORD_SUCCESS;
+ }
+ else if (store_type == STPTRW || store_type == STPTRD || store_type == SCW
+ || store_type == SCD)
+ {
+ int data_size;
+ int rj_num;
+ int imm;
+ uint64_t rj_val;
+ uint64_t address;
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ imm = loongarch_decode_imm ("10:14<<2",
+ loongarch_insn_r->insn, 1);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
+ address = rj_val + imm;
+ switch (store_type)
+ {
+ case STPTRW:
+ case SCW:
+ data_size = 4;
+ break;
+ case STPTRD:
+ case SCD:
+ data_size = 8;
+ break;
+ default:
+ data_size = 0;
+ break;
+ }
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = address;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems,
+ loongarch_insn_r->mem_rec_count, record_buf_mem);
+ return LOONGARCH_RECORD_SUCCESS;
+ }
+
+ return LOONGARCH_RECORD_UNSUPPORTED;
+}
+
+/* Record handler for atomic memory access instructions. */
+
+static unsigned int
+loongarch_record_am_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int rj_num, rd_num;
+ int word_or_double;
+ int data_size;
+ uint64_t address;
+ uint32_t record_buf[1];
+ uint64_t record_buf_mem[2];
+ rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ word_or_double = loongarch_decode_imm ("15:1",
+ loongarch_insn_r->insn, 0);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &address);
+ data_size = word_or_double == 1 ? 8 : 4;
+ record_buf[0] = rd_num;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = address;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems, loongarch_insn_r->mem_rec_count,
+ record_buf_mem);
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for condition load instructions. */
+
+static unsigned int
+loongarch_record_cond_load_insn (loongarch_insn_record *loongarch_insn_r)
+ {
+ int rd_num, rj_num, rk_num, fd_num;
+ uint64_t rj_val, rk_val;
+ rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ fd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
+
+ if ((is_ldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
+ || (is_ldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
+ {
+ uint32_t record_buf[1];
+ record_buf[0] = rd_num;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ }
+ else if ((is_fldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
+ || (is_fldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
+ {
+ uint32_t record_buf[1];
+ record_buf[0] = fd_num;
+ loongarch_insn_r->reg_rec_count = 1;
+
+ REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
+ record_buf);
+ }
+
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for condition store instructions. */
+
+static unsigned int
+loongarch_record_cond_store_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ int rj_num, rk_num;
+ int data_size;
+ uint64_t rj_val, rk_val;
+ uint32_t length_opcode;
+ rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
+ rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
+
+ if ((is_stgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
+ || (is_stle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
+ {
+ uint64_t record_buf_mem[2];
+ length_opcode = loongarch_insn_r->insn & 0x00018000;
+ switch (length_opcode)
+ {
+ case 0x00000000:
+ data_size = 1;
+ break;
+ case 0x00008000:
+ data_size = 2;
+ break;
+ case 0x00010000:
+ data_size = 4;
+ break;
+ case 0x00018000:
+ data_size = 8;
+ break;
+ default:
+ data_size = 0;
+ break;
+ }
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = rj_val;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems,
+ loongarch_insn_r->mem_rec_count, record_buf_mem);
+ }
+ else if ((is_fstgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
+ || (is_fstle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
+ {
+ uint64_t record_buf_mem[2];
+ length_opcode = loongarch_insn_r->insn & 0x00008000;
+ switch (length_opcode)
+ {
+ case 0x00000000:
+ data_size = 4;
+ break;
+ case 0x00008000:
+ data_size = 8;
+ break;
+ default:
+ data_size = 0;
+ break;
+ }
+ record_buf_mem[0] = data_size;
+ record_buf_mem[1] = rj_val;
+ loongarch_insn_r->mem_rec_count = 1;
+
+ MEM_ALLOC (loongarch_insn_r->loongarch_mems,
+ loongarch_insn_r->mem_rec_count,record_buf_mem);
+ }
+
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Record handler for special instructions like privilege instructions,
+ barrier instructions and cache related instructions etc. */
+
+static unsigned int
+loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
+{
+ return LOONGARCH_RECORD_SUCCESS;
+}
+
+/* Decode insns type and invoke its record handler. */
+
+static unsigned int
+loongarch_record_decode_insn_handler (loongarch_insn_record *loongarch_insn_r)
+{
+ if (is_data_process_insn (loongarch_insn_r->insn))
+ return loongarch_record_data_proc_insn (loongarch_insn_r);
+ else if (is_jump_insn (loongarch_insn_r->insn))
+ return loongarch_record_jump_insn (loongarch_insn_r);
+ else if (is_store_insn (loongarch_insn_r->insn))
+ return loongarch_record_store_insn (loongarch_insn_r);
+ else if (is_read_time_insn (loongarch_insn_r->insn))
+ return loongarch_record_read_time_insn (loongarch_insn_r);
+ else if (is_float_insn (loongarch_insn_r->insn))
+ return loongarch_record_float_insn (loongarch_insn_r);
+ else if (is_special_insn (loongarch_insn_r->insn))
+ return loongarch_record_special_insn (loongarch_insn_r);
+ else if (is_am_insn (loongarch_insn_r->insn))
+ return loongarch_record_am_insn (loongarch_insn_r);
+ else if (is_cond_load_insn (loongarch_insn_r->insn))
+ return loongarch_record_cond_load_insn (loongarch_insn_r);
+ else if (is_cond_store_insn (loongarch_insn_r->insn))
+ return loongarch_record_cond_store_insn (loongarch_insn_r);
+
+ return LOONGARCH_RECORD_UNSUPPORTED;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list
+ return -1 if something is wrong. */
+
+int
+loongarch_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+ int rec_num = 0;
+ uint32_t ret = 0;
+ loongarch_insn_record loongarch_record;
+
+ /* reset the content of loongarch_record */
+ memset (&loongarch_record, 0, sizeof (loongarch_insn_record));
+
+ /* write the loongarch_record */
+ loongarch_record.gdbarch = gdbarch;
+ loongarch_record.regcache = regcache;
+ loongarch_record.this_addr = insn_addr;
+
+ /* Get the current instruction */
+ loongarch_record.insn = (uint32_t) loongarch_fetch_instruction (insn_addr);
+ ret = loongarch_record_decode_insn_handler (&loongarch_record);
+ if (ret == LOONGARCH_RECORD_UNSUPPORTED)
+ {
+ gdb_printf (gdb_stderr,
+ _("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ loongarch_record.insn,
+ paddress (gdbarch, insn_addr));
+ ret = -1;
+ }
+ if (ret == LOONGARCH_RECORD_SUCCESS)
+ {
+ /* Record registers. */
+ record_full_arch_list_add_reg (loongarch_record.regcache,
+ LOONGARCH_PC_REGNUM);
+ if (loongarch_record.reg_rec_count)
+ {
+ for (rec_num = 0; rec_num < loongarch_record.reg_rec_count; rec_num++)
+ {
+ if (record_full_arch_list_add_reg (loongarch_record.regcache,
+ loongarch_record.regs[rec_num]))
+ ret = -1;
+ }
+ }
+
+ /* Record memories. */
+ if (loongarch_record.mem_rec_count)
+ {
+ for (rec_num = 0; rec_num < loongarch_record.mem_rec_count; rec_num++)
+ {
+ if (record_full_arch_list_add_mem
+ ((CORE_ADDR)loongarch_record.loongarch_mems[rec_num].addr,
+ loongarch_record.loongarch_mems[rec_num].len))
+ ret = -1;
+ }
+ }
+
+ if (record_full_arch_list_add_end ())
+ ret = -1;
+ }
+
+ return ret;
+}
+
void _initialize_loongarch_tdep ();
void
_initialize_loongarch_tdep ()
diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
index 5c8108182ad..a148363c795 100644
--- a/gdb/loongarch-tdep.h
+++ b/gdb/loongarch-tdep.h
@@ -44,4 +44,7 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) = nullptr;
};
+extern int loongarch_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
#endif /* LOONGARCH_TDEP_H */
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 410f99e3350..9b994a9f640 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -3698,6 +3698,7 @@ proc supports_process_record {} {
if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
|| [istarget "i\[34567\]86-*-linux*"]
|| [istarget "aarch64*-*-linux*"]
+ || [istarget "loongarch*-*-linux*"]
|| [istarget "powerpc*-*-linux*"]
|| [istarget "s390*-*-linux*"] } {
return 1
@@ -3717,6 +3718,7 @@ proc supports_reverse {} {
if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
|| [istarget "i\[34567\]86-*-linux*"]
|| [istarget "aarch64*-*-linux*"]
+ || [istarget "loongarch*-*-linux*"]
|| [istarget "powerpc*-*-linux*"]
|| [istarget "s390*-*-linux*"] } {
return 1
--
2.38.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay
2024-11-13 9:53 [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support Hui Li
2024-11-13 9:53 ` [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record Hui Li
2024-11-13 9:53 ` [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support Hui Li
@ 2024-11-13 9:53 ` Hui Li
2024-11-13 13:01 ` Guinevere Larsen
2024-11-13 9:53 ` [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc Hui Li
3 siblings, 1 reply; 13+ messages in thread
From: Hui Li @ 2024-11-13 9:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Tiezhu Yang
The process record and replay function also need record Linux
system call instruction. This patch adds LoongArch system call
number definitions in gdb/arch/loongarch-syscall.h, and adds
loongarch_linux_syscall_record() in gdb/loongarch-linux-tdep.c
to record system call execute log. With this patch, the mainly
function of process record/replay and reverse debugging has been
implemented.
The LoongArch system call numbers definitions are obtained from Linux kernel.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h
Signed-off-by: Hui Li <lihui@loongson.cn>
---
gdb/arch/loongarch-syscall.h | 348 +++++++++++++++++++++
gdb/loongarch-linux-tdep.c | 565 +++++++++++++++++++++++++++++++++++
gdb/loongarch-tdep.c | 18 ++
gdb/loongarch-tdep.h | 4 +
4 files changed, 935 insertions(+)
create mode 100644 gdb/arch/loongarch-syscall.h
diff --git a/gdb/arch/loongarch-syscall.h b/gdb/arch/loongarch-syscall.h
new file mode 100644
index 00000000000..6f10b1d33e7
--- /dev/null
+++ b/gdb/arch/loongarch-syscall.h
@@ -0,0 +1,348 @@
+/* Target-dependent code for LoongArch
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* The syscall number definitions are obtained from Linux kernel header file.
+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h */
+
+#ifndef ARCH_LOONGARCH_SYSCALL_H
+#define ARCH_LOONGARCH_SYSCALL_H
+
+enum loongarch_syscall
+{
+ loongarch_sys_io_setup = 0,
+ loongarch_sys_io_destroy = 1,
+ loongarch_sys_io_submit = 2,
+ loongarch_sys_io_cancel = 3,
+ loongarch_sys_io_getevents = 4,
+ loongarch_sys_setxattr = 5,
+ loongarch_sys_lsetxattr = 6,
+ loongarch_sys_fsetxattr = 7,
+ loongarch_sys_getxattr = 8,
+ loongarch_sys_lgetxattr = 9,
+ loongarch_sys_fgetxattr = 10,
+ loongarch_sys_listxattr = 11,
+ loongarch_sys_llistxattr = 12,
+ loongarch_sys_flistxattr = 13,
+ loongarch_sys_removexattr = 14,
+ loongarch_sys_lremovexattr = 15,
+ loongarch_sys_fremovexattr = 16,
+ loongarch_sys_getcwd = 17,
+ loongarch_sys_lookup_dcookie = 18,
+ loongarch_sys_eventfd2 = 19,
+ loongarch_sys_epoll_create1 = 20,
+ loongarch_sys_epoll_ctl = 21,
+ loongarch_sys_epoll_pwait = 22,
+ loongarch_sys_dup = 23,
+ loongarch_sys_dup3 = 24,
+ loongarch_sys_fcntl = 25,
+ loongarch_sys_inotify_init1 = 26,
+ loongarch_sys_inotify_add_watch = 27,
+ loongarch_sys_inotify_rm_watch = 28,
+ loongarch_sys_ioctl = 29,
+ loongarch_sys_ioprio_set = 30,
+ loongarch_sys_ioprio_get = 31,
+ loongarch_sys_flock = 32,
+ loongarch_sys_mknodat = 33,
+ loongarch_sys_mkdirat = 34,
+ loongarch_sys_unlinkat = 35,
+ loongarch_sys_symlinkat = 36,
+ loongarch_sys_linkat = 37,
+
+ loongarch_sys_umount2 = 39,
+ loongarch_sys_mount = 40,
+ loongarch_sys_pivot_root = 41,
+ loongarch_sys_nfsservctl = 42,
+ loongarch_sys_statfs = 43,
+ loongarch_sys_fstatfs = 44,
+ loongarch_sys_truncate = 45,
+ loongarch_sys_ftruncate = 46,
+ loongarch_sys_fallocate = 47,
+ loongarch_sys_faccessat = 48,
+ loongarch_sys_chdir = 49,
+ loongarch_sys_fchdir = 50,
+ loongarch_sys_chroot = 51,
+ loongarch_sys_fchmod = 52,
+ loongarch_sys_fchmodat = 53,
+ loongarch_sys_fchownat = 54,
+ loongarch_sys_fchown = 55,
+ loongarch_sys_openat = 56,
+ loongarch_sys_close = 57,
+ loongarch_sys_vhangup = 58,
+ loongarch_sys_pipe2 = 59,
+ loongarch_sys_quotactl = 60,
+ loongarch_sys_getdents64 = 61,
+ loongarch_sys_lseek = 62,
+ loongarch_sys_read = 63,
+ loongarch_sys_write = 64,
+ loongarch_sys_readv = 65,
+ loongarch_sys_writev = 66,
+ loongarch_sys_pread64 = 67,
+ loongarch_sys_pwrite64 = 68,
+ loongarch_sys_preadv = 69,
+ loongarch_sys_pwritev = 70,
+ loongarch_sys_sendfile = 71,
+ loongarch_sys_pselect6 = 72,
+ loongarch_sys_ppoll = 73,
+ loongarch_sys_signalfd4 = 74,
+ loongarch_sys_vmsplice = 75,
+ loongarch_sys_splice = 76,
+ loongarch_sys_tee = 77,
+ loongarch_sys_readlinkat = 78,
+ loongarch_sys_newfstatat = 79,
+ loongarch_sys_fstat = 80,
+ loongarch_sys_sync = 81,
+ loongarch_sys_fsync = 82,
+ loongarch_sys_fdatasync = 83,
+ loongarch_sys_sync_file_range = 84,
+ loongarch_sys_timerfd_create = 85,
+ loongarch_sys_timerfd_settime = 86,
+ loongarch_sys_timerfd_gettime = 87,
+ loongarch_sys_utimensat = 88,
+ loongarch_sys_acct = 89,
+ loongarch_sys_capget = 90,
+ loongarch_sys_capset = 91,
+ loongarch_sys_personality = 92,
+ loongarch_sys_exit = 93,
+ loongarch_sys_exit_group = 94,
+ loongarch_sys_waitid = 95,
+ loongarch_sys_set_tid_address = 96,
+ loongarch_sys_unshare = 97,
+ loongarch_sys_futex = 98,
+ loongarch_sys_set_robust_list = 99,
+ loongarch_sys_get_robust_list = 100,
+ loongarch_sys_nanosleep = 101,
+ loongarch_sys_getitimer = 102,
+ loongarch_sys_setitimer = 103,
+ loongarch_sys_kexec_load = 104,
+ loongarch_sys_init_module = 105,
+ loongarch_sys_delete_module = 106,
+ loongarch_sys_timer_create = 107,
+ loongarch_sys_timer_gettime = 108,
+ loongarch_sys_timer_getoverrun = 109,
+ loongarch_sys_timer_settime = 110,
+ loongarch_sys_timer_delete = 111,
+ loongarch_sys_clock_settime = 112,
+ loongarch_sys_clock_gettime = 113,
+ loongarch_sys_clock_getres = 114,
+ loongarch_sys_clock_nanosleep = 115,
+ loongarch_sys_syslog = 116,
+ loongarch_sys_ptrace = 117,
+ loongarch_sys_sched_setparam = 118,
+ loongarch_sys_sched_setscheduler = 119,
+ loongarch_sys_sched_getscheduler = 120,
+ loongarch_sys_sched_getparam = 121,
+ loongarch_sys_sched_setaffinity = 122,
+ loongarch_sys_sched_getaffinity = 123,
+ loongarch_sys_sched_yield = 124,
+ loongarch_sys_sched_get_priority_max = 125,
+ loongarch_sys_sched_get_priority_min = 126,
+ loongarch_sys_sched_rr_get_interval = 127,
+ loongarch_sys_restart_syscall = 128,
+ loongarch_sys_kill = 129,
+ loongarch_sys_tkill = 130,
+ loongarch_sys_tgkill = 131,
+ loongarch_sys_sigaltstack = 132,
+ loongarch_sys_rt_sigsuspend = 133,
+ loongarch_sys_rt_sigaction = 134,
+ loongarch_sys_rt_sigprocmask = 135,
+ loongarch_sys_rt_sigpending = 136,
+ loongarch_sys_rt_sigtimedwait = 137,
+ loongarch_sys_rt_sigqueueinfo = 138,
+ loongarch_sys_rt_sigreturn = 139,
+ loongarch_sys_setpriority = 140,
+ loongarch_sys_getpriority = 141,
+ loongarch_sys_reboot = 142,
+ loongarch_sys_setregid = 143,
+ loongarch_sys_setgid = 144,
+ loongarch_sys_setreuid = 145,
+ loongarch_sys_setuid = 146,
+ loongarch_sys_setresuid = 147,
+ loongarch_sys_getresuid = 148,
+ loongarch_sys_setresgid = 149,
+ loongarch_sys_getresgid = 150,
+ loongarch_sys_setfsuid = 151,
+ loongarch_sys_setfsgid = 152,
+ loongarch_sys_times = 153,
+ loongarch_sys_setpgid = 154,
+ loongarch_sys_getpgid = 155,
+ loongarch_sys_getsid = 156,
+ loongarch_sys_setsid = 157,
+ loongarch_sys_getgroups = 158,
+ loongarch_sys_setgroups = 159,
+ loongarch_sys_uname = 160,
+ loongarch_sys_sethostname = 161,
+ loongarch_sys_setdomainname = 162,
+
+ loongarch_sys_getrusage = 165,
+ loongarch_sys_umask = 166,
+ loongarch_sys_prctl = 167,
+ loongarch_sys_getcpu = 168,
+ loongarch_sys_gettimeofday = 169,
+ loongarch_sys_settimeofday = 170,
+ loongarch_sys_adjtimex = 171,
+ loongarch_sys_getpid = 172,
+ loongarch_sys_getppid = 173,
+ loongarch_sys_getuid = 174,
+ loongarch_sys_geteuid = 175,
+ loongarch_sys_getgid = 176,
+ loongarch_sys_getegid = 177,
+ loongarch_sys_gettid = 178,
+ loongarch_sys_sysinfo = 179,
+ loongarch_sys_mq_open = 180,
+ loongarch_sys_mq_unlink = 181,
+ loongarch_sys_mq_timedsend = 182,
+ loongarch_sys_mq_timedreceive = 183,
+ loongarch_sys_mq_notify = 184,
+ loongarch_sys_mq_getsetattr = 185,
+ loongarch_sys_msgget = 186,
+ loongarch_sys_msgctl = 187,
+ loongarch_sys_msgrcv = 188,
+ loongarch_sys_msgsnd = 189,
+ loongarch_sys_semget = 190,
+ loongarch_sys_semctl = 191,
+ loongarch_sys_semtimedop = 192,
+ loongarch_sys_semop = 193,
+ loongarch_sys_shmget = 194,
+ loongarch_sys_shmctl = 195,
+ loongarch_sys_shmat = 196,
+ loongarch_sys_shmdt = 197,
+ loongarch_sys_socket = 198,
+ loongarch_sys_socketpair = 199,
+ loongarch_sys_bind = 200,
+ loongarch_sys_listen = 201,
+ loongarch_sys_accept = 202,
+ loongarch_sys_connect = 203,
+ loongarch_sys_getsockname = 204,
+ loongarch_sys_getpeername = 205,
+ loongarch_sys_sendto = 206,
+ loongarch_sys_recvfrom = 207,
+ loongarch_sys_setsockopt = 208,
+ loongarch_sys_getsockopt = 209,
+ loongarch_sys_shutdown = 210,
+ loongarch_sys_sendmsg = 211,
+ loongarch_sys_recvmsg = 212,
+ loongarch_sys_readahead = 213,
+ loongarch_sys_brk = 214,
+ loongarch_sys_munmap = 215,
+ loongarch_sys_mremap = 216,
+ loongarch_sys_add_key = 217,
+ loongarch_sys_request_key = 218,
+ loongarch_sys_keyctl = 219,
+ loongarch_sys_clone = 220,
+ loongarch_sys_execve = 221,
+ loongarch_sys_mmap = 222,
+ loongarch_sys_fadvise64 = 223,
+ loongarch_sys_swapon = 224,
+ loongarch_sys_swapoff = 225,
+ loongarch_sys_mprotect = 226,
+ loongarch_sys_msync = 227,
+ loongarch_sys_mlock = 228,
+ loongarch_sys_munlock = 229,
+ loongarch_sys_mlockall = 230,
+ loongarch_sys_munlockall = 231,
+ loongarch_sys_mincore = 232,
+ loongarch_sys_madvise = 233,
+ loongarch_sys_remap_file_pages = 234,
+ loongarch_sys_mbind = 235,
+ loongarch_sys_get_mempolicy = 236,
+ loongarch_sys_set_mempolicy = 237,
+ loongarch_sys_migrate_pages = 238,
+ loongarch_sys_move_pages = 239,
+ loongarch_sys_rt_tgsigqueueinfo = 240,
+ loongarch_sys_perf_event_open = 241,
+ loongarch_sys_accept4 = 242,
+ loongarch_sys_recvmmsg = 243,
+ loongarch_sys_wait4 = 260,
+ loongarch_sys_prlimit64 = 261,
+ loongarch_sys_fanotify_init = 262,
+ loongarch_sys_fanotify_mark = 263,
+ loongarch_sys_name_to_handle_at = 264,
+ loongarch_sys_open_by_handle_at = 265,
+ loongarch_sys_clock_adjtime = 266,
+ loongarch_sys_syncfs = 267,
+ loongarch_sys_setns = 268,
+ loongarch_sys_sendmmsg = 269,
+ loongarch_sys_process_vm_readv = 270,
+ loongarch_sys_process_vm_writev = 271,
+ loongarch_sys_kcmp = 272,
+ loongarch_sys_finit_module = 273,
+ loongarch_sys_sched_setattr = 274,
+ loongarch_sys_sched_getattr = 275,
+ loongarch_sys_renameat2 = 276,
+ loongarch_sys_seccomp = 277,
+ loongarch_sys_getrandom = 278,
+ loongarch_sys_memfd_create = 279,
+ loongarch_sys_bpf = 280,
+ loongarch_sys_execveat = 281,
+ loongarch_sys_userfaultfd = 282,
+ loongarch_sys_membarrier = 283,
+ loongarch_sys_mlock2 = 284,
+ loongarch_sys_copy_file_range = 285,
+ loongarch_sys_preadv2 = 286,
+ loongarch_sys_pwritev2 = 287,
+ loongarch_sys_pkey_mprotect = 288,
+ loongarch_sys_pkey_alloc = 289,
+ loongarch_sys_pkey_free = 290,
+ loongarch_sys_statx = 291,
+ loongarch_sys_io_pgetevents = 292,
+ loongarch_sys_rseq = 293,
+ loongarch_sys_kexec_file_load = 294,
+
+ loongarch_sys_pidfd_send_signal = 424,
+ loongarch_sys_io_uring_setup = 425,
+ loongarch_sys_io_uring_enter = 426,
+ loongarch_sys_io_uring_register = 427,
+ loongarch_sys_open_tree = 428,
+ loongarch_sys_move_mount = 429,
+ loongarch_sys_fsopen = 430,
+ loongarch_sys_fsconfig = 431,
+ loongarch_sys_fsmount = 432,
+ loongarch_sys_fspick = 433,
+ loongarch_sys_pidfd_open = 434,
+ loongarch_sys_clone3 = 435,
+ loongarch_sys_close_range = 436,
+ loongarch_sys_openat2 = 437,
+ loongarch_sys_pidfd_getfd = 438,
+ loongarch_sys_faccessat2 = 439,
+ loongarch_sys_process_madvise = 440,
+ loongarch_sys_epoll_pwait2 = 441,
+ loongarch_sys_mount_setattr = 442,
+ loongarch_sys_quotactl_fd = 443,
+ loongarch_sys_landlock_create_ruleset = 444,
+ loongarch_sys_landlock_add_rule = 445,
+ loongarch_sys_landlock_restrict_self = 446,
+
+ loongarch_sys_process_mrelease = 448,
+ loongarch_sys_futex_waitv = 449,
+ loongarch_sys_set_mempolicy_home_node = 450,
+ loongarch_sys_cachestat = 451,
+ loongarch_sys_fchmodat2 = 452,
+ loongarch_sys_map_shadow_stack = 453,
+ loongarch_sys_futex_wake = 454,
+ loongarch_sys_futex_wait = 455,
+ loongarch_sys_futex_requeue = 456,
+ loongarch_sys_statmount = 457,
+ loongarch_sys_listmount = 458,
+ loongarch_sys_lsm_get_self_attr = 459,
+ loongarch_sys_lsm_set_self_attr = 460,
+ loongarch_sys_lsm_list_modules = 461,
+ loongarch_sys_mseal = 462,
+ loongarch_sys_syscalls = 463,
+};
+
+#endif /* ARCH_LOONGARCH_INSN_H */
diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
index 86e7ed8a0bc..a027edd07e5 100644
--- a/gdb/loongarch-linux-tdep.c
+++ b/gdb/loongarch-linux-tdep.c
@@ -18,15 +18,21 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "arch/loongarch-syscall.h"
#include "extract-store-integer.h"
+#include "gdbarch.h"
#include "glibc-tdep.h"
#include "inferior.h"
+#include "linux-record.h"
#include "linux-tdep.h"
#include "loongarch-tdep.h"
+#include "record-full.h"
+#include "regset.h"
#include "solib-svr4.h"
#include "target-descriptions.h"
#include "trad-frame.h"
#include "tramp-frame.h"
+#include "value.h"
#include "xml-syscall.h"
/* The syscall's XML filename for LoongArch. */
@@ -566,6 +572,561 @@ loongarch_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread
return ret;
}
+static linux_record_tdep loongarch_linux_record_tdep;
+
+/* loongarch_canonicalize_syscall maps syscall ids from the native LoongArch
+ linux set of syscall ids into a canonical set of syscall ids used by
+ process record. */
+
+static enum gdb_syscall
+loongarch_canonicalize_syscall (enum loongarch_syscall syscall_number)
+{
+#define SYSCALL_MAP(SYSCALL) case loongarch_sys_##SYSCALL: \
+ return gdb_sys_##SYSCALL
+
+#define UNSUPPORTED_SYSCALL_MAP(SYSCALL) case loongarch_sys_##SYSCALL: \
+ return gdb_sys_no_syscall
+
+ switch(syscall_number)
+ {
+ SYSCALL_MAP (io_setup);
+ SYSCALL_MAP (io_destroy);
+ SYSCALL_MAP (io_submit);
+ SYSCALL_MAP (io_cancel);
+ SYSCALL_MAP (io_getevents);
+ SYSCALL_MAP (setxattr);
+ SYSCALL_MAP (lsetxattr);
+ SYSCALL_MAP (fsetxattr);
+ SYSCALL_MAP (getxattr);
+ SYSCALL_MAP (lgetxattr);
+ SYSCALL_MAP (fgetxattr);
+ SYSCALL_MAP (listxattr);
+ SYSCALL_MAP (llistxattr);
+ SYSCALL_MAP (flistxattr);
+ SYSCALL_MAP (removexattr);
+ SYSCALL_MAP (lremovexattr);
+ SYSCALL_MAP (fremovexattr);
+ SYSCALL_MAP (getcwd);
+ SYSCALL_MAP (lookup_dcookie);
+ SYSCALL_MAP (eventfd2);
+ SYSCALL_MAP (epoll_create1);
+ SYSCALL_MAP (epoll_ctl);
+ SYSCALL_MAP (epoll_pwait);
+ SYSCALL_MAP (dup);
+ SYSCALL_MAP (dup3);
+ SYSCALL_MAP (fcntl);
+ SYSCALL_MAP (inotify_init1);
+ SYSCALL_MAP (inotify_add_watch);
+ SYSCALL_MAP (inotify_rm_watch);
+ SYSCALL_MAP (ioctl);
+ SYSCALL_MAP (ioprio_set);
+ SYSCALL_MAP (ioprio_get);
+ SYSCALL_MAP (flock);
+ SYSCALL_MAP (mknodat);
+ SYSCALL_MAP (mkdirat);
+ SYSCALL_MAP (unlinkat);
+ SYSCALL_MAP (symlinkat);
+ SYSCALL_MAP (linkat);
+ UNSUPPORTED_SYSCALL_MAP (umount2);
+ SYSCALL_MAP (mount);
+ SYSCALL_MAP (pivot_root);
+ SYSCALL_MAP (nfsservctl);
+ SYSCALL_MAP (statfs);
+ SYSCALL_MAP (truncate);
+ SYSCALL_MAP (ftruncate);
+ SYSCALL_MAP (fallocate);
+ SYSCALL_MAP (faccessat);
+ SYSCALL_MAP (fchdir);
+ SYSCALL_MAP (chroot);
+ SYSCALL_MAP (fchmod);
+ SYSCALL_MAP (fchmodat);
+ SYSCALL_MAP (fchownat);
+ SYSCALL_MAP (fchown);
+ SYSCALL_MAP (openat);
+ SYSCALL_MAP (close);
+ SYSCALL_MAP (vhangup);
+ SYSCALL_MAP (pipe2);
+ SYSCALL_MAP (quotactl);
+ SYSCALL_MAP (getdents64);
+ SYSCALL_MAP (lseek);
+ SYSCALL_MAP (read);
+ SYSCALL_MAP (write);
+ SYSCALL_MAP (readv);
+ SYSCALL_MAP (writev);
+ SYSCALL_MAP (pread64);
+ SYSCALL_MAP (pwrite64);
+ UNSUPPORTED_SYSCALL_MAP (preadv);
+ UNSUPPORTED_SYSCALL_MAP (pwritev);
+ SYSCALL_MAP (sendfile);
+ SYSCALL_MAP (pselect6);
+ SYSCALL_MAP (ppoll);
+ UNSUPPORTED_SYSCALL_MAP (signalfd4);
+ SYSCALL_MAP (vmsplice);
+ SYSCALL_MAP (splice);
+ SYSCALL_MAP (tee);
+ SYSCALL_MAP (readlinkat);
+ SYSCALL_MAP (newfstatat);
+ SYSCALL_MAP (fstat);
+ SYSCALL_MAP (sync);
+ SYSCALL_MAP (fsync);
+ SYSCALL_MAP (fdatasync);
+ SYSCALL_MAP (sync_file_range);
+ UNSUPPORTED_SYSCALL_MAP (timerfd_create);
+ UNSUPPORTED_SYSCALL_MAP (timerfd_settime);
+ UNSUPPORTED_SYSCALL_MAP (timerfd_gettime);
+ UNSUPPORTED_SYSCALL_MAP (utimensat);
+ SYSCALL_MAP (acct);
+ SYSCALL_MAP (capget);
+ SYSCALL_MAP (capset);
+ SYSCALL_MAP (personality);
+ SYSCALL_MAP (exit);
+ SYSCALL_MAP (exit_group);
+ SYSCALL_MAP (waitid);
+ SYSCALL_MAP (set_tid_address);
+ SYSCALL_MAP (unshare);
+ SYSCALL_MAP (futex);
+ SYSCALL_MAP (set_robust_list);
+ SYSCALL_MAP (get_robust_list);
+ SYSCALL_MAP (nanosleep);
+ SYSCALL_MAP (getitimer);
+ SYSCALL_MAP (setitimer);
+ SYSCALL_MAP (kexec_load);
+ SYSCALL_MAP (init_module);
+ SYSCALL_MAP (delete_module);
+ SYSCALL_MAP (timer_create);
+ SYSCALL_MAP (timer_settime);
+ SYSCALL_MAP (timer_gettime);
+ SYSCALL_MAP (timer_getoverrun);
+ SYSCALL_MAP (timer_delete);
+ SYSCALL_MAP (clock_settime);
+ SYSCALL_MAP (clock_gettime);
+ SYSCALL_MAP (clock_getres);
+ SYSCALL_MAP (clock_nanosleep);
+ SYSCALL_MAP (syslog);
+ SYSCALL_MAP (ptrace);
+ SYSCALL_MAP (sched_setparam);
+ SYSCALL_MAP (sched_setscheduler);
+ SYSCALL_MAP (sched_getscheduler);
+ SYSCALL_MAP (sched_getparam);
+ SYSCALL_MAP (sched_setaffinity);
+ SYSCALL_MAP (sched_getaffinity);
+ SYSCALL_MAP (sched_yield);
+ SYSCALL_MAP (sched_get_priority_max);
+ SYSCALL_MAP (sched_get_priority_min);
+ SYSCALL_MAP (sched_rr_get_interval);
+ SYSCALL_MAP (kill);
+ SYSCALL_MAP (tkill);
+ SYSCALL_MAP (tgkill);
+ SYSCALL_MAP (sigaltstack);
+ SYSCALL_MAP (rt_sigsuspend);
+ SYSCALL_MAP (rt_sigaction);
+ SYSCALL_MAP (rt_sigprocmask);
+ SYSCALL_MAP (rt_sigpending);
+ SYSCALL_MAP (rt_sigtimedwait);
+ SYSCALL_MAP (rt_sigqueueinfo);
+ SYSCALL_MAP (rt_sigreturn);
+ SYSCALL_MAP (setpriority);
+ SYSCALL_MAP (getpriority);
+ SYSCALL_MAP (reboot);
+ SYSCALL_MAP (setregid);
+ SYSCALL_MAP (setgid);
+ SYSCALL_MAP (setreuid);
+ SYSCALL_MAP (setuid);
+ SYSCALL_MAP (setresuid);
+ SYSCALL_MAP (getresuid);
+ SYSCALL_MAP (setresgid);
+ SYSCALL_MAP (getresgid);
+ SYSCALL_MAP (setfsuid);
+ SYSCALL_MAP (setfsgid);
+ SYSCALL_MAP (times);
+ SYSCALL_MAP (setpgid);
+ SYSCALL_MAP (getpgid);
+ SYSCALL_MAP (getsid);
+ SYSCALL_MAP (setsid);
+ SYSCALL_MAP (getgroups);
+ SYSCALL_MAP (setgroups);
+ SYSCALL_MAP (uname);
+ SYSCALL_MAP (sethostname);
+ SYSCALL_MAP (setdomainname);
+ SYSCALL_MAP (getrusage);
+ SYSCALL_MAP (umask);
+ SYSCALL_MAP (prctl);
+ SYSCALL_MAP (getcpu);
+ SYSCALL_MAP (gettimeofday);
+ SYSCALL_MAP (settimeofday);
+ SYSCALL_MAP (adjtimex);
+ SYSCALL_MAP (getpid);
+ SYSCALL_MAP (getppid);
+ SYSCALL_MAP (getuid);
+ SYSCALL_MAP (geteuid);
+ SYSCALL_MAP (getgid);
+ SYSCALL_MAP (getegid);
+ SYSCALL_MAP (gettid);
+ SYSCALL_MAP (sysinfo);
+ SYSCALL_MAP (mq_open);
+ SYSCALL_MAP (mq_unlink);
+ SYSCALL_MAP (mq_timedsend);
+ SYSCALL_MAP (mq_timedreceive);
+ SYSCALL_MAP (mq_notify);
+ SYSCALL_MAP (mq_getsetattr);
+ SYSCALL_MAP (msgget);
+ SYSCALL_MAP (msgctl);
+ SYSCALL_MAP (msgrcv);
+ SYSCALL_MAP (msgsnd);
+ SYSCALL_MAP (semget);
+ SYSCALL_MAP (semctl);
+ SYSCALL_MAP (semtimedop);
+ SYSCALL_MAP (semop);
+ SYSCALL_MAP (shmget);
+ SYSCALL_MAP (shmctl);
+ SYSCALL_MAP (shmat);
+ SYSCALL_MAP (shmdt);
+ SYSCALL_MAP (socket);
+ SYSCALL_MAP (socketpair);
+ SYSCALL_MAP (bind);
+ SYSCALL_MAP (listen);
+ SYSCALL_MAP (accept);
+ SYSCALL_MAP (connect);
+ SYSCALL_MAP (getsockname);
+ SYSCALL_MAP (getpeername);
+ SYSCALL_MAP (sendto);
+ SYSCALL_MAP (recvfrom);
+ SYSCALL_MAP (setsockopt);
+ SYSCALL_MAP (getsockopt);
+ SYSCALL_MAP (shutdown);
+ SYSCALL_MAP (sendmsg);
+ SYSCALL_MAP (recvmsg);
+ SYSCALL_MAP (readahead);
+ SYSCALL_MAP (brk);
+ SYSCALL_MAP (munmap);
+ SYSCALL_MAP (mremap);
+ SYSCALL_MAP (add_key);
+ SYSCALL_MAP (request_key);
+ SYSCALL_MAP (keyctl);
+ SYSCALL_MAP (clone);
+ SYSCALL_MAP (execve);
+
+ case loongarch_sys_mmap:
+ return gdb_sys_mmap2;
+
+ SYSCALL_MAP (fadvise64);
+ SYSCALL_MAP (swapon);
+ SYSCALL_MAP (swapoff);
+ SYSCALL_MAP (mprotect);
+ SYSCALL_MAP (msync);
+ SYSCALL_MAP (mlock);
+ SYSCALL_MAP (munlock);
+ SYSCALL_MAP (mlockall);
+ SYSCALL_MAP (munlockall);
+ SYSCALL_MAP (mincore);
+ SYSCALL_MAP (madvise);
+ SYSCALL_MAP (remap_file_pages);
+ SYSCALL_MAP (mbind);
+ SYSCALL_MAP (get_mempolicy);
+ SYSCALL_MAP (set_mempolicy);
+ SYSCALL_MAP (migrate_pages);
+ SYSCALL_MAP (move_pages);
+ UNSUPPORTED_SYSCALL_MAP (rt_tgsigqueueinfo);
+ UNSUPPORTED_SYSCALL_MAP (perf_event_open);
+ UNSUPPORTED_SYSCALL_MAP (accept4);
+ UNSUPPORTED_SYSCALL_MAP (recvmmsg);
+ SYSCALL_MAP (wait4);
+ UNSUPPORTED_SYSCALL_MAP (prlimit64);
+ UNSUPPORTED_SYSCALL_MAP (fanotify_init);
+ UNSUPPORTED_SYSCALL_MAP (fanotify_mark);
+ UNSUPPORTED_SYSCALL_MAP (name_to_handle_at);
+ UNSUPPORTED_SYSCALL_MAP (open_by_handle_at);
+ UNSUPPORTED_SYSCALL_MAP (clock_adjtime);
+ UNSUPPORTED_SYSCALL_MAP (syncfs);
+ UNSUPPORTED_SYSCALL_MAP (setns);
+ UNSUPPORTED_SYSCALL_MAP (sendmmsg);
+ UNSUPPORTED_SYSCALL_MAP (process_vm_readv);
+ UNSUPPORTED_SYSCALL_MAP (process_vm_writev);
+ UNSUPPORTED_SYSCALL_MAP (kcmp);
+ UNSUPPORTED_SYSCALL_MAP (finit_module);
+ UNSUPPORTED_SYSCALL_MAP (sched_setattr);
+ UNSUPPORTED_SYSCALL_MAP (sched_getattr);
+ UNSUPPORTED_SYSCALL_MAP (renameat2);
+ UNSUPPORTED_SYSCALL_MAP (seccomp);
+ SYSCALL_MAP (getrandom);
+ UNSUPPORTED_SYSCALL_MAP (memfd_create);
+ UNSUPPORTED_SYSCALL_MAP (bpf);
+ UNSUPPORTED_SYSCALL_MAP (execveat);
+ UNSUPPORTED_SYSCALL_MAP (userfaultfd);
+ UNSUPPORTED_SYSCALL_MAP (membarrier);
+ UNSUPPORTED_SYSCALL_MAP (mlock2);
+ UNSUPPORTED_SYSCALL_MAP (copy_file_range);
+ UNSUPPORTED_SYSCALL_MAP (preadv2);
+ UNSUPPORTED_SYSCALL_MAP (pwritev2);
+ UNSUPPORTED_SYSCALL_MAP (pkey_mprotect);
+ UNSUPPORTED_SYSCALL_MAP (pkey_alloc);
+ UNSUPPORTED_SYSCALL_MAP (pkey_free);
+ SYSCALL_MAP (statx);
+ UNSUPPORTED_SYSCALL_MAP (io_pgetevents);
+ UNSUPPORTED_SYSCALL_MAP (rseq);
+ UNSUPPORTED_SYSCALL_MAP (kexec_file_load);
+ UNSUPPORTED_SYSCALL_MAP (pidfd_send_signal);
+ UNSUPPORTED_SYSCALL_MAP (io_uring_setup);
+ UNSUPPORTED_SYSCALL_MAP (io_uring_enter);
+ UNSUPPORTED_SYSCALL_MAP (io_uring_register);
+ UNSUPPORTED_SYSCALL_MAP (open_tree);
+ UNSUPPORTED_SYSCALL_MAP (move_mount);
+ UNSUPPORTED_SYSCALL_MAP (fsopen);
+ UNSUPPORTED_SYSCALL_MAP (fsconfig);
+ UNSUPPORTED_SYSCALL_MAP (fsmount);
+ UNSUPPORTED_SYSCALL_MAP (fspick);
+ UNSUPPORTED_SYSCALL_MAP (pidfd_open);
+ UNSUPPORTED_SYSCALL_MAP (clone3);
+ UNSUPPORTED_SYSCALL_MAP (close_range);
+ UNSUPPORTED_SYSCALL_MAP (openat2);
+ UNSUPPORTED_SYSCALL_MAP (pidfd_getfd);
+ UNSUPPORTED_SYSCALL_MAP (faccessat2);
+ UNSUPPORTED_SYSCALL_MAP (process_madvise);
+ UNSUPPORTED_SYSCALL_MAP (epoll_pwait2);
+ UNSUPPORTED_SYSCALL_MAP (mount_setattr);
+ UNSUPPORTED_SYSCALL_MAP (quotactl_fd);
+ UNSUPPORTED_SYSCALL_MAP (landlock_create_ruleset);
+ UNSUPPORTED_SYSCALL_MAP (landlock_add_rule);
+ UNSUPPORTED_SYSCALL_MAP (landlock_restrict_self);
+ UNSUPPORTED_SYSCALL_MAP (process_mrelease);
+ UNSUPPORTED_SYSCALL_MAP (futex_waitv);
+ UNSUPPORTED_SYSCALL_MAP (set_mempolicy_home_node);
+ UNSUPPORTED_SYSCALL_MAP (cachestat);
+ UNSUPPORTED_SYSCALL_MAP (fchmodat2);
+ UNSUPPORTED_SYSCALL_MAP (map_shadow_stack);
+ UNSUPPORTED_SYSCALL_MAP (futex_wake);
+ UNSUPPORTED_SYSCALL_MAP (futex_wait);
+ UNSUPPORTED_SYSCALL_MAP (futex_requeue);
+ UNSUPPORTED_SYSCALL_MAP (statmount);
+ UNSUPPORTED_SYSCALL_MAP (listmount);
+ UNSUPPORTED_SYSCALL_MAP (lsm_get_self_attr);
+ UNSUPPORTED_SYSCALL_MAP (lsm_set_self_attr);
+ UNSUPPORTED_SYSCALL_MAP (lsm_list_modules);
+ UNSUPPORTED_SYSCALL_MAP (mseal);
+ UNSUPPORTED_SYSCALL_MAP (syscalls);
+ default:
+ return gdb_sys_no_syscall;
+ }
+}
+
+static int
+loongarch_record_all_but_pc_registers (struct regcache *regcache)
+{
+
+ /* Record General purpose Registers. */
+ for (int i = 0; i < 32; ++i)
+ if (record_full_arch_list_add_reg (regcache, i))
+ return -1;
+
+ /* Record orig_a0 */
+ if (record_full_arch_list_add_reg (regcache, LOONGARCH_ORIG_A0_REGNUM))
+ return -1;
+
+ /* Record badvaddr */
+ if (record_full_arch_list_add_reg (regcache, LOONGARCH_BADV_REGNUM))
+ return -1;
+
+ return 0;
+}
+
+/* Handler for LoongArch architechture system call instruction recording. */
+
+static int
+loongarch_linux_syscall_record (struct regcache *regcache,
+ unsigned long syscall_number)
+{
+ int ret = 0;
+ enum gdb_syscall syscall_gdb;
+
+ syscall_gdb =
+ loongarch_canonicalize_syscall ((enum loongarch_syscall) syscall_number);
+
+ if (syscall_gdb < 0)
+ {
+ gdb_printf (gdb_stderr,
+ _("Process record and replay target doesn't "
+ "support syscall number %s\n"),
+ plongest (syscall_number));
+ }
+
+ if (syscall_gdb == gdb_sys_sigreturn || syscall_gdb == gdb_sys_rt_sigreturn)
+ return loongarch_record_all_but_pc_registers (regcache);
+
+ ret = record_linux_system_call (syscall_gdb, regcache,
+ &loongarch_linux_record_tdep);
+
+ if (ret != 0)
+ return ret;
+
+ /* Record the return value of the system call. */
+ if (record_full_arch_list_add_reg (regcache, LOONGARCH_A0_REGNUM))
+ return -1;
+
+ return 0;
+}
+
+/* Initialize the loongarch_linux_record_tdep. These values are the size
+ of the type that will be used in a system call. They are obtained from
+ Linux Kernel source. */
+
+static void
+Init_loongarch_linux_record_tdep (struct gdbarch *gdbarch)
+{
+ loongarch_linux_record_tdep.size_pointer
+ = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+ loongarch_linux_record_tdep.size_tms = 32;
+ loongarch_linux_record_tdep.size_loff_t = 8;
+ loongarch_linux_record_tdep.size_flock = 32;
+ loongarch_linux_record_tdep.size_oldold_utsname = 45;
+ loongarch_linux_record_tdep.size_ustat = 32;
+ loongarch_linux_record_tdep.size_old_sigaction = 32;
+ loongarch_linux_record_tdep.size_old_sigset_t = 8;
+ loongarch_linux_record_tdep.size_rlimit = 16;
+ loongarch_linux_record_tdep.size_rusage = 144;
+ loongarch_linux_record_tdep.size_timeval = 16;
+ loongarch_linux_record_tdep.size_timezone = 8;
+ loongarch_linux_record_tdep.size_old_gid_t = 4;
+ loongarch_linux_record_tdep.size_old_uid_t = 4;
+ loongarch_linux_record_tdep.size_fd_set = 128;
+ loongarch_linux_record_tdep.size_old_dirent = 280;
+ loongarch_linux_record_tdep.size_statfs = 120;
+ loongarch_linux_record_tdep.size_statfs64 = 120;
+ loongarch_linux_record_tdep.size_sockaddr = 16;
+ loongarch_linux_record_tdep.size_int
+ = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT;
+ loongarch_linux_record_tdep.size_long
+ = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ loongarch_linux_record_tdep.size_ulong
+ = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+ loongarch_linux_record_tdep.size_msghdr = 56;
+ loongarch_linux_record_tdep.size_itimerval = 32;
+ loongarch_linux_record_tdep.size_stat = 144;
+ loongarch_linux_record_tdep.size_old_utsname = 325;
+ loongarch_linux_record_tdep.size_sysinfo = 112;
+ loongarch_linux_record_tdep.size_msqid_ds = 120;
+ loongarch_linux_record_tdep.size_shmid_ds = 112;
+ loongarch_linux_record_tdep.size_new_utsname = 390;
+ loongarch_linux_record_tdep.size_timex = 208;
+ loongarch_linux_record_tdep.size_mem_dqinfo = 72;
+ loongarch_linux_record_tdep.size_if_dqblk = 72;
+ loongarch_linux_record_tdep.size_fs_quota_stat = 80;
+ loongarch_linux_record_tdep.size_timespec = 16;
+ loongarch_linux_record_tdep.size_pollfd = 8;
+ loongarch_linux_record_tdep.size_NFS_FHSIZE = 32;
+ loongarch_linux_record_tdep.size_knfsd_fh = 132;
+ loongarch_linux_record_tdep.size_TASK_COMM_LEN = 16;
+ loongarch_linux_record_tdep.size_sigaction = 24;
+ loongarch_linux_record_tdep.size_sigset_t = 8;
+ loongarch_linux_record_tdep.size_siginfo_t = 128;
+ loongarch_linux_record_tdep.size_cap_user_data_t = 8;
+ loongarch_linux_record_tdep.size_stack_t = 24;
+ loongarch_linux_record_tdep.size_off_t = 8;
+ loongarch_linux_record_tdep.size_stat64 = 144;
+ loongarch_linux_record_tdep.size_gid_t = 4;
+ loongarch_linux_record_tdep.size_uid_t = 4;
+ loongarch_linux_record_tdep.size_PAGE_SIZE = 0x4000;
+ loongarch_linux_record_tdep.size_flock64 = 32;
+ loongarch_linux_record_tdep.size_user_desc = 16;
+ loongarch_linux_record_tdep.size_io_event = 32;
+ loongarch_linux_record_tdep.size_iocb = 64;
+ loongarch_linux_record_tdep.size_epoll_event = 12;
+ loongarch_linux_record_tdep.size_itimerspec = 32;
+ loongarch_linux_record_tdep.size_mq_attr = 64;
+ loongarch_linux_record_tdep.size_termios = 36;
+ loongarch_linux_record_tdep.size_termios2 = 44;
+ loongarch_linux_record_tdep.size_pid_t = 4;
+ loongarch_linux_record_tdep.size_winsize = 8;
+ loongarch_linux_record_tdep.size_serial_struct = 72;
+ loongarch_linux_record_tdep.size_serial_icounter_struct = 80;
+ loongarch_linux_record_tdep.size_hayes_esp_config = 12;
+ loongarch_linux_record_tdep.size_size_t = 8;
+ loongarch_linux_record_tdep.size_iovec = 16;
+ loongarch_linux_record_tdep.size_time_t = 8;
+
+ /* These values are the second argument of system call "sys_ioctl".
+ They are obtained from Linux Kernel source. */
+ loongarch_linux_record_tdep.ioctl_TCGETS = 0x5401;
+ loongarch_linux_record_tdep.ioctl_TCSETS = 0x5402;
+ loongarch_linux_record_tdep.ioctl_TCSETSW = 0x5403;
+ loongarch_linux_record_tdep.ioctl_TCSETSF = 0x5404;
+ loongarch_linux_record_tdep.ioctl_TCGETA = 0x5405;
+ loongarch_linux_record_tdep.ioctl_TCSETA = 0x5406;
+ loongarch_linux_record_tdep.ioctl_TCSETAW = 0x5407;
+ loongarch_linux_record_tdep.ioctl_TCSETAF = 0x5408;
+ loongarch_linux_record_tdep.ioctl_TCSBRK = 0x5409;
+ loongarch_linux_record_tdep.ioctl_TCXONC = 0x540a;
+ loongarch_linux_record_tdep.ioctl_TCFLSH = 0x540b;
+ loongarch_linux_record_tdep.ioctl_TIOCEXCL = 0x540c;
+ loongarch_linux_record_tdep.ioctl_TIOCNXCL = 0x540d;
+ loongarch_linux_record_tdep.ioctl_TIOCSCTTY = 0x540e;
+ loongarch_linux_record_tdep.ioctl_TIOCGPGRP = 0x540f;
+ loongarch_linux_record_tdep.ioctl_TIOCSPGRP = 0x5410;
+ loongarch_linux_record_tdep.ioctl_TIOCOUTQ = 0x5411;
+ loongarch_linux_record_tdep.ioctl_TIOCSTI = 0x5412;
+ loongarch_linux_record_tdep.ioctl_TIOCGWINSZ = 0x5413;
+ loongarch_linux_record_tdep.ioctl_TIOCSWINSZ = 0x5414;
+ loongarch_linux_record_tdep.ioctl_TIOCMGET = 0x5415;
+ loongarch_linux_record_tdep.ioctl_TIOCMBIS = 0x5416;
+ loongarch_linux_record_tdep.ioctl_TIOCMBIC = 0x5417;
+ loongarch_linux_record_tdep.ioctl_TIOCMSET = 0x5418;
+ loongarch_linux_record_tdep.ioctl_TIOCGSOFTCAR = 0x5419;
+ loongarch_linux_record_tdep.ioctl_TIOCSSOFTCAR = 0x541a;
+ loongarch_linux_record_tdep.ioctl_FIONREAD = 0x541b;
+ loongarch_linux_record_tdep.ioctl_TIOCINQ = 0x541b;
+ loongarch_linux_record_tdep.ioctl_TIOCLINUX = 0x541c;
+ loongarch_linux_record_tdep.ioctl_TIOCCONS = 0x541d;
+ loongarch_linux_record_tdep.ioctl_TIOCGSERIAL = 0x541e;
+ loongarch_linux_record_tdep.ioctl_TIOCSSERIAL = 0x541f;
+ loongarch_linux_record_tdep.ioctl_TIOCPKT = 0x5420;
+ loongarch_linux_record_tdep.ioctl_FIONBIO = 0x5421;
+ loongarch_linux_record_tdep.ioctl_TIOCNOTTY = 0x5422;
+ loongarch_linux_record_tdep.ioctl_TIOCSETD = 0x5423;
+ loongarch_linux_record_tdep.ioctl_TIOCGETD = 0x5424;
+ loongarch_linux_record_tdep.ioctl_TCSBRKP = 0x5425;
+ loongarch_linux_record_tdep.ioctl_TIOCTTYGSTRUCT = 0x5426;
+ loongarch_linux_record_tdep.ioctl_TIOCSBRK = 0x5427;
+ loongarch_linux_record_tdep.ioctl_TIOCCBRK = 0x5428;
+ loongarch_linux_record_tdep.ioctl_TIOCGSID = 0x5429;
+ loongarch_linux_record_tdep.ioctl_TCGETS2 = 0x802c542a;
+ loongarch_linux_record_tdep.ioctl_TCSETS2 = 0x402c542b;
+ loongarch_linux_record_tdep.ioctl_TCSETSW2 = 0x402c542c;
+ loongarch_linux_record_tdep.ioctl_TCSETSF2 = 0x402c542d;
+ loongarch_linux_record_tdep.ioctl_TIOCGPTN = 0x80045430;
+ loongarch_linux_record_tdep.ioctl_TIOCSPTLCK = 0x40045431;
+ loongarch_linux_record_tdep.ioctl_FIONCLEX = 0x5450;
+ loongarch_linux_record_tdep.ioctl_FIOCLEX = 0x5451;
+ loongarch_linux_record_tdep.ioctl_FIOASYNC = 0x5452;
+ loongarch_linux_record_tdep.ioctl_TIOCSERCONFIG = 0x5453;
+ loongarch_linux_record_tdep.ioctl_TIOCSERGWILD = 0x5454;
+ loongarch_linux_record_tdep.ioctl_TIOCSERSWILD = 0x5455;
+ loongarch_linux_record_tdep.ioctl_TIOCGLCKTRMIOS = 0x5456;
+ loongarch_linux_record_tdep.ioctl_TIOCSLCKTRMIOS = 0x5457;
+ loongarch_linux_record_tdep.ioctl_TIOCSERGSTRUCT = 0x5458;
+ loongarch_linux_record_tdep.ioctl_TIOCSERGETLSR = 0x5459;
+ loongarch_linux_record_tdep.ioctl_TIOCSERGETMULTI = 0x545a;
+ loongarch_linux_record_tdep.ioctl_TIOCSERSETMULTI = 0x545b;
+ loongarch_linux_record_tdep.ioctl_TIOCMIWAIT = 0x545c;
+ loongarch_linux_record_tdep.ioctl_TIOCGICOUNT = 0x545d;
+ loongarch_linux_record_tdep.ioctl_TIOCGHAYESESP = 0x545e;
+ loongarch_linux_record_tdep.ioctl_TIOCSHAYESESP = 0x545f;
+ loongarch_linux_record_tdep.ioctl_FIOQSIZE = 0x5460;
+
+ /* These values are the second argument of system call "sys_fcntl"
+ and "sys_fcntl64". They are obtained from Linux Kernel source. */
+ loongarch_linux_record_tdep.fcntl_F_GETLK = 5;
+ loongarch_linux_record_tdep.fcntl_F_GETLK64 = 12;
+ loongarch_linux_record_tdep.fcntl_F_SETLK64 = 13;
+ loongarch_linux_record_tdep.fcntl_F_SETLKW64 = 14;
+
+ loongarch_linux_record_tdep.arg1 = LOONGARCH_A0_REGNUM + 0;
+ loongarch_linux_record_tdep.arg2 = LOONGARCH_A0_REGNUM + 1;
+ loongarch_linux_record_tdep.arg3 = LOONGARCH_A0_REGNUM + 2;
+ loongarch_linux_record_tdep.arg4 = LOONGARCH_A0_REGNUM + 3;
+ loongarch_linux_record_tdep.arg5 = LOONGARCH_A0_REGNUM + 4;
+ loongarch_linux_record_tdep.arg6 = LOONGARCH_A0_REGNUM + 5;
+ loongarch_linux_record_tdep.arg7 = LOONGARCH_A0_REGNUM + 6;
+}
+
/* Initialize LoongArch Linux ABI info. */
static void
@@ -605,6 +1166,10 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Reversible debugging, process record. */
set_gdbarch_process_record (gdbarch, loongarch_process_record);
+
+ /* Syscall record. */
+ tdep->loongarch_syscall_record = loongarch_linux_syscall_record;
+ Init_loongarch_linux_record_tdep (gdbarch);
}
/* Initialize LoongArch Linux target support. */
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index cf72c48b573..b13e35c8e33 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -2388,6 +2388,22 @@ loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
return LOONGARCH_RECORD_SUCCESS;
}
+/* Record handler for syscall instructions. */
+
+static unsigned int
+loongarch_syscall_insn_record (loongarch_insn_record *loongarch_insn_r)
+{
+ uint64_t syscall_number;
+ struct loongarch_gdbarch_tdep *tdep
+ = gdbarch_tdep<loongarch_gdbarch_tdep> (loongarch_insn_r->gdbarch);
+
+ regcache_raw_read_unsigned (loongarch_insn_r->regcache, LOONGARCH_A7_REGNUM,
+ &syscall_number);
+
+ return tdep->loongarch_syscall_record (loongarch_insn_r->regcache,
+ syscall_number);
+}
+
/* Decode insns type and invoke its record handler. */
static unsigned int
@@ -2411,6 +2427,8 @@ loongarch_record_decode_insn_handler (loongarch_insn_record *loongarch_insn_r)
return loongarch_record_cond_load_insn (loongarch_insn_r);
else if (is_cond_store_insn (loongarch_insn_r->insn))
return loongarch_record_cond_store_insn (loongarch_insn_r);
+ else if (is_syscall_insn (loongarch_insn_r->insn))
+ return loongarch_syscall_insn_record (loongarch_insn_r);
return LOONGARCH_RECORD_UNSUPPORTED;
}
diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
index a148363c795..62f7edc1c45 100644
--- a/gdb/loongarch-tdep.h
+++ b/gdb/loongarch-tdep.h
@@ -40,6 +40,10 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
/* Features about the abi that impact how the gdbarch is configured. */
struct loongarch_gdbarch_features abi_features;
+ /* syscall record. */
+ int (*loongarch_syscall_record) (struct regcache *regcache,
+ unsigned long syscall_number) = nullptr;
+
/* Return the expected next PC if FRAME is stopped at a syscall instruction. */
CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) = nullptr;
};
--
2.38.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc
2024-11-13 9:53 [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support Hui Li
` (2 preceding siblings ...)
2024-11-13 9:53 ` [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay Hui Li
@ 2024-11-13 9:53 ` Hui Li
2024-11-13 15:01 ` Eli Zaretskii
3 siblings, 1 reply; 13+ messages in thread
From: Hui Li @ 2024-11-13 9:53 UTC (permalink / raw)
To: gdb-patches; +Cc: Tiezhu Yang
At present, process record/replay and reverse debugging has been
implemented on LoongArch. Update the NEWS and doc to record this
new change.
Signed-off-by: Hui Li <lihui@loongson.cn>
---
gdb/NEWS | 3 +++
gdb/doc/gdb.texinfo | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 20837bb7b17..17d8ffb8fba 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -51,6 +51,9 @@
* The Ada 'Object_Size attribute is now supported.
+* Support for process record/replay and reverse debugging on loongarch*-linux*
+ targets has been added.
+
* Python API
** Added gdb.record.clear. Clears the trace data of the current recording.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 99720f1206e..e5be0112a5e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7759,7 +7759,7 @@ previous instruction; otherwise, it will work in record mode, if the
platform supports reverse execution, or stop if not.
Currently, process record and replay is supported on ARM, Aarch64,
-Moxie, PowerPC, PowerPC64, S/390, and x86 (i386/amd64) running
+LoongArch, Moxie, PowerPC, PowerPC64, S/390, and x86 (i386/amd64) running
GNU/Linux. Process record and replay can be used both when native
debugging, and when remote debugging via @code{gdbserver}.
--
2.38.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record
2024-11-13 9:53 ` [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record Hui Li
@ 2024-11-13 12:03 ` Guinevere Larsen
2024-11-19 13:07 ` Hui Li
0 siblings, 1 reply; 13+ messages in thread
From: Guinevere Larsen @ 2024-11-13 12:03 UTC (permalink / raw)
To: Hui Li, gdb-patches; +Cc: Tiezhu Yang
On 11/13/24 6:53 AM, Hui Li wrote:
> GDB provides a special process record function that can record a log
> of the process execution. The core of this feature is need to record
> the execution of all instructions. This patch adds opcode definitions
> and judgments in gdb/arch/loongarch-insn.h. This is preparation for
> later patch on LoongArch, there is no effect for the other archs with
> this patch.
>
> The LoongArch opcode and mask definitions are obtained from
> https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=opcodes/loongarch-opc.c
> LoongArch instruction description refer to the LoongArch Reference Manual:
> https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
>
> Signed-off-by: Hui Li <lihui@loongson.cn>
> ---
I'm not familiar with loongarch, so I can't really review this specific
patch in depth, but I have a bit of personal preference below.
> gdb/arch/loongarch-insn.h | 1361 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 1361 insertions(+)
> create mode 100644 gdb/arch/loongarch-insn.h
>
<snip>
> +
> +#define is_insn(insval,mask,funccode) (((insval) & (mask)) == funccode)
I personally would prefer if this was defined as a tiny inline function,
like riscv-tdep.c does it. I tend to find them easier to debug. I would
extend this to the is_<type>_insn macros below as well. But I don't
expect to work on loongarch (or even have loongarch hardware) any time
soon, so feel free to ignore my preferences.
If kept as a macro, funccode should probably be in parenthesis as well.
--
Cheers,
Guinevere Larsen
She/Her/Hers
> +
> +#define is_data_process_insn(insval) \
> + ((is_insn(insval,MASK_CLO_W,OP_CLO_W)) || \
> + (is_insn(insval,MASK_CLZ_W,OP_CLZ_W)) || \
> + (is_insn(insval,MASK_CTO_W,OP_CTO_W)) || \
> + (is_insn(insval,MASK_CTZ_W,OP_CTZ_W)) || \
> + (is_insn(insval,MASK_CLO_D,OP_CLO_D)) || \
> + (is_insn(insval,MASK_CLZ_D,OP_CLZ_D)) || \
> + (is_insn(insval,MASK_CTO_D,OP_CTO_D)) || \
> + (is_insn(insval,MASK_CTZ_D,OP_CTZ_D)) || \
> + (is_insn(insval,MASK_REVB_2H,OP_REVB_2H)) || \
> + (is_insn(insval,MASK_REVB_4H,OP_REVB_4H)) || \
> + (is_insn(insval,MASK_REVB_2W,OP_REVB_2W)) || \
> + (is_insn(insval,MASK_REVH_2W,OP_REVH_2W)) || \
> + (is_insn(insval,MASK_REVH_D,OP_REVH_D)) || \
> + (is_insn(insval,MASK_BITREV_4B,OP_BITREV_4B)) || \
> + (is_insn(insval,MASK_BITREV_8B,OP_BITREV_8B)) || \
> + (is_insn(insval,MASK_BITREV_W,OP_BITREV_W)) || \
> + (is_insn(insval,MASK_BITREV_D,OP_BITREV_D)) || \
> + (is_insn(insval,MASK_EXT_W_H,OP_EXT_W_H)) || \
> + (is_insn(insval,MASK_EXT_W_B,OP_EXT_W_B)) || \
> + (is_insn(insval,MASK_CPUCFG,OP_CPUCFG)) || \
> + (is_insn(insval,MASK_ALSL_W,OP_ALSL_W)) || \
> + (is_insn(insval,MASK_ALSL_WU,OP_ALSL_WU)) || \
> + (is_insn(insval,MASK_BYTEPICK_W,OP_BYTEPICK_W)) || \
> + (is_insn(insval,MASK_BYTEPICK_D,OP_BYTEPICK_D)) || \
> + (is_insn(insval,MASK_ADD_W,OP_ADD_W)) || \
> + (is_insn(insval,MASK_ADD_D,OP_ADD_D)) || \
> + (is_insn(insval,MASK_SUB_W,OP_SUB_W)) || \
> + (is_insn(insval,MASK_SUB_D,OP_SUB_D)) || \
> + (is_insn(insval,MASK_SLT,OP_SLT)) || \
> + (is_insn(insval,MASK_SLTU,OP_SLTU)) || \
> + (is_insn(insval,MASK_MASKEQZ,OP_MASKEQZ)) || \
> + (is_insn(insval,MASK_MASKNEZ,OP_MASKNEZ)) || \
> + (is_insn(insval,MASK_NOR,OP_NOR)) || \
> + (is_insn(insval,MASK_AND,OP_AND)) || \
> + (is_insn(insval,MASK_OR,OP_OR)) || \
> + (is_insn(insval,MASK_XOR,OP_XOR)) || \
> + (is_insn(insval,MASK_ORN,OP_ORN)) || \
> + (is_insn(insval,MASK_ANDN,OP_ANDN)) || \
> + (is_insn(insval,MASK_SLL_W,OP_SLL_W)) || \
> + (is_insn(insval,MASK_SRL_W,OP_SRL_W)) || \
> + (is_insn(insval,MASK_SRA_W,OP_SRA_W)) || \
> + (is_insn(insval,MASK_SLL_D,OP_SLL_D)) || \
> + (is_insn(insval,MASK_SRL_D,OP_SRL_D)) || \
> + (is_insn(insval,MASK_SRA_D,OP_SRA_D)) || \
> + (is_insn(insval,MASK_ROTR_W,OP_ROTR_W)) || \
> + (is_insn(insval,MASK_ROTR_D,OP_ROTR_D)) || \
> + (is_insn(insval,MASK_MUL_W,OP_MUL_W)) || \
> + (is_insn(insval,MASK_MULH_W,OP_MULH_W)) || \
> + (is_insn(insval,MASK_MULH_WU,OP_MULH_WU)) || \
> + (is_insn(insval,MASK_MUL_D,OP_MUL_D)) || \
> + (is_insn(insval,MASK_MULH_D,OP_MULH_D)) || \
> + (is_insn(insval,MASK_MULH_DU,OP_MULH_DU)) || \
> + (is_insn(insval,MASK_MULW_D_W,OP_MULW_D_W)) || \
> + (is_insn(insval,MASK_MULW_D_WU,OP_MULW_D_WU)) || \
> + (is_insn(insval,MASK_DIV_W,OP_DIV_W)) || \
> + (is_insn(insval,MASK_MOD_W,OP_MOD_W)) || \
> + (is_insn(insval,MASK_DIV_WU,OP_DIV_WU)) || \
> + (is_insn(insval,MASK_MOD_WU,OP_MOD_WU)) || \
> + (is_insn(insval,MASK_DIV_D,OP_DIV_D)) || \
> + (is_insn(insval,MASK_MOD_D,OP_MOD_D)) || \
> + (is_insn(insval,MASK_DIV_DU,OP_DIV_DU)) || \
> + (is_insn(insval,MASK_MOD_DU,OP_MOD_DU)) || \
> + (is_insn(insval,MASK_CRC_W_B_W,OP_CRC_W_B_W)) || \
> + (is_insn(insval,MASK_CRC_W_H_W,OP_CRC_W_H_W)) || \
> + (is_insn(insval,MASK_CRC_W_W_W,OP_CRC_W_W_W)) || \
> + (is_insn(insval,MASK_CRC_W_D_W,OP_CRC_W_D_W)) || \
> + (is_insn(insval,MASK_CRCC_W_B_W,OP_CRCC_W_B_W)) || \
> + (is_insn(insval,MASK_CRCC_W_H_W,OP_CRCC_W_H_W)) || \
> + (is_insn(insval,MASK_CRCC_W_W_W,OP_CRCC_W_W_W)) || \
> + (is_insn(insval,MASK_CRCC_W_D_W,OP_CRCC_W_D_W)) || \
> + (is_insn(insval,MASK_ALSL_D,OP_ALSL_D)) || \
> + (is_insn(insval,MASK_SLLI_W,OP_SLLI_W)) || \
> + (is_insn(insval,MASK_SLLI_D,OP_SLLI_D)) || \
> + (is_insn(insval,MASK_SRLI_W,OP_SRLI_W)) || \
> + (is_insn(insval,MASK_SRLI_D,OP_SRLI_D)) || \
> + (is_insn(insval,MASK_SRAI_W,OP_SRAI_W)) || \
> + (is_insn(insval,MASK_SRAI_D,OP_SRAI_D)) || \
> + (is_insn(insval,MASK_ROTRI_W,OP_ROTRI_W)) || \
> + (is_insn(insval,MASK_ROTRI_D,OP_ROTRI_D)) || \
> + (is_insn(insval,MASK_BSTRINS_W,OP_BSTRINS_W)) || \
> + (is_insn(insval,MASK_BSTRPICK_W,OP_BSTRPICK_W)) || \
> + (is_insn(insval,MASK_BSTRINS_D,OP_BSTRINS_D)) || \
> + (is_insn(insval,MASK_BSTRPICK_D,OP_BSTRPICK_D)) || \
> + (is_insn(insval,MASK_MOVFR2GR_S,OP_MOVFR2GR_S)) || \
> + (is_insn(insval,MASK_MOVFRH2GR_S,OP_MOVFRH2GR_S)) || \
> + (is_insn(insval,MASK_MOVFCSR2GR,OP_MOVFCSR2GR)) || \
> + (is_insn(insval,MASK_MOVCF2GR,OP_MOVCF2GR)) || \
> + (is_insn(insval,MASK_MOVFR2GR_D,OP_MOVFR2GR_D)) || \
> + (is_insn(insval,MASK_SLTI,OP_SLTI)) || \
> + (is_insn(insval,MASK_SLTUI,OP_SLTUI)) || \
> + (is_insn(insval,MASK_ADDI_W,OP_ADDI_W)) || \
> + (is_insn(insval,MASK_ADDI_D,OP_ADDI_D)) || \
> + (is_insn(insval,MASK_LU52I_D,OP_LU52I_D)) || \
> + (is_insn(insval,MASK_ANDI,OP_ANDI)) || \
> + (is_insn(insval,MASK_ORI,OP_ORI)) || \
> + (is_insn(insval,MASK_XORI,OP_XORI)) || \
> + (is_insn(insval,MASK_ADDU16I_D,OP_ADDU16I_D)) || \
> + (is_insn(insval,MASK_LU12I_W,OP_LU12I_W)) || \
> + (is_insn(insval,MASK_LU32I_D,OP_LU32I_D)) || \
> + (is_insn(insval,MASK_PCADDI,OP_PCADDI)) || \
> + (is_insn(insval,MASK_PCALAU12I,OP_PCALAU12I)) || \
> + (is_insn(insval,MASK_PCADDU12I,OP_PCADDU12I)) || \
> + (is_insn(insval,MASK_PCADDU18I,OP_PCADDU18I)) || \
> + (is_insn(insval,MASK_LDDIR,OP_LDDIR)) || \
> + (is_insn(insval,MASK_LL_W,OP_LL_W)) || \
> + (is_insn(insval,MASK_LL_D,OP_LL_D)) || \
> + (is_insn(insval,MASK_LDPTR_W,OP_LDPTR_W)) || \
> + (is_insn(insval,MASK_LDPTR_D,OP_LDPTR_D)) || \
> + (is_insn(insval,MASK_LD_B,OP_LD_B)) || \
> + (is_insn(insval,MASK_LD_H,OP_LD_H)) || \
> + (is_insn(insval,MASK_LD_W,OP_LD_W)) || \
> + (is_insn(insval,MASK_LD_D,OP_LD_D)) || \
> + (is_insn(insval,MASK_LD_BU,OP_LD_BU)) || \
> + (is_insn(insval,MASK_LD_HU,OP_LD_HU)) || \
> + (is_insn(insval,MASK_LD_WU,OP_LD_WU)) || \
> + (is_insn(insval,MASK_LDX_B,OP_LDX_B)) || \
> + (is_insn(insval,MASK_LDX_H,OP_LDX_H)) || \
> + (is_insn(insval,MASK_LDX_W,OP_LDX_W)) || \
> + (is_insn(insval,MASK_LDX_D,OP_LDX_D)) || \
> + (is_insn(insval,MASK_LDX_BU,OP_LDX_BU)) || \
> + (is_insn(insval,MASK_LDX_HU,OP_LDX_HU)) || \
> + (is_insn(insval,MASK_LDX_WU,OP_LDX_WU)) || \
> + (is_insn(insval,MASK_VLD,OP_VLD)) || \
> + (is_insn(insval,MASK_XVLD,OP_XVLD)))
> +
> +#define is_read_time_insn(insval) \
> + ((is_insn(insval,MASK_RDTIMEL_W,OP_RDTIMEL_W)) || \
> + (is_insn(insval,MASK_RDTIMEH_W,OP_RDTIMEH_W)) || \
> + (is_insn(insval,MASK_RDTIME_D,OP_RDTIME_D)))
> +
> +#define is_syscall_insn(insval) \
> + (is_insn(insval,MASK_SYSCALL,OP_SYSCALL))
> +
> +#define is_float_insn(insval) \
> + ((is_insn(insval,MASK_FADD_S,OP_FADD_S)) || \
> + (is_insn(insval,MASK_SUB_S,OP_SUB_S)) || \
> + (is_insn(insval,MASK_FDIV_S,OP_FDIV_S)) || \
> + (is_insn(insval,MASK_FMAX_S,OP_FMAX_S)) || \
> + (is_insn(insval,MASK_FMIN_S,OP_FMIN_S)) || \
> + (is_insn(insval,MASK_FMAXA_S,OP_FMAXA_S)) || \
> + (is_insn(insval,MASK_FMINA_S,OP_FMINA_S)) || \
> + (is_insn(insval,MASK_FSCALEB_S,OP_FSCALEB_S)) || \
> + (is_insn(insval,MASK_FCOPYSIGN_S,OP_FCOPYSIGN_S)) || \
> + (is_insn(insval,MASK_FABS_S,OP_FABS_S)) || \
> + (is_insn(insval,MASK_FNEG_S,OP_FNEG_S)) || \
> + (is_insn(insval,MASK_FLOGB_S,OP_FLOGB_S)) || \
> + (is_insn(insval,MASK_FCLASS_S,OP_FCLASS_S)) || \
> + (is_insn(insval,MASK_FSQRT_S,OP_FSQRT_S)) || \
> + (is_insn(insval,MASK_FRECIP_S,OP_FRECIP_S)) || \
> + (is_insn(insval,MASK_FRSQRT_S,OP_FRSQRT_S)) || \
> + (is_insn(insval,MASK_FRECIPE_S,OP_FRECIPE_S)) || \
> + (is_insn(insval,MASK_FRSQRTE_S,OP_FRSQRTE_S)) || \
> + (is_insn(insval,MASK_FMOV_S,OP_FMOV_S)) || \
> + (is_insn(insval,MASK_MOVGR2FR_W,OP_MOVGR2FR_W)) || \
> + (is_insn(insval,MASK_MOVGR2FRH_W,OP_MOVGR2FRH_W)) || \
> + (is_insn(insval,MASK_MOVGR2FCSR,OP_MOVGR2FCSR)) || \
> + (is_insn(insval,MASK_MOVFR2CF,OP_MOVFR2CF)) || \
> + (is_insn(insval,MASK_MOVCF2FR,OP_MOVCF2FR)) || \
> + (is_insn(insval,MASK_MOVGR2CF,OP_MOVGR2CF)) || \
> + (is_insn(insval,MASK_FTINTRM_W_S,OP_FTINTRM_W_S)) || \
> + (is_insn(insval,MASK_FTINTRM_L_S,OP_FTINTRM_L_S)) || \
> + (is_insn(insval,MASK_FTINTRP_W_S,OP_FTINTRP_W_S)) || \
> + (is_insn(insval,MASK_FTINTRP_L_S,OP_FTINTRP_L_S)) || \
> + (is_insn(insval,MASK_FTINTRZ_W_S,OP_FTINTRZ_W_S)) || \
> + (is_insn(insval,MASK_FTINTRZ_L_S,OP_FTINTRZ_L_S)) || \
> + (is_insn(insval,MASK_FTINTRNE_W_S,OP_FTINTRNE_W_S)) || \
> + (is_insn(insval,MASK_FTINTRNE_L_S,OP_FTINTRNE_L_S)) || \
> + (is_insn(insval,MASK_FTINT_W_S,OP_FTINT_W_S)) || \
> + (is_insn(insval,MASK_FTINT_L_S,OP_FTINT_L_S)) || \
> + (is_insn(insval,MASK_FFINT_S_W,OP_FFINT_S_W)) || \
> + (is_insn(insval,MASK_FFINT_S_L,OP_FFINT_S_L)) || \
> + (is_insn(insval,MASK_FRINT_S,OP_FRINT_S)) || \
> + (is_insn(insval,MASK_FADD_D,OP_FADD_D)) || \
> + (is_insn(insval,MASK_FSUB_D,OP_FSUB_D)) || \
> + (is_insn(insval,MASK_FMUL_D,OP_FMUL_D)) || \
> + (is_insn(insval,MASK_FDIV_D,OP_FDIV_D)) || \
> + (is_insn(insval,MASK_FMAX_D,OP_FMAX_D)) || \
> + (is_insn(insval,MASK_FMIN_D,OP_FMIN_D)) || \
> + (is_insn(insval,MASK_FMAXA_D,OP_FMAXA_D)) || \
> + (is_insn(insval,MASK_FMINA_D,OP_FMINA_D)) || \
> + (is_insn(insval,MASK_FSCALEB_D,OP_FSCALEB_D)) || \
> + (is_insn(insval,MASK_FCOPYSIGN_D,OP_FCOPYSIGN_D)) || \
> + (is_insn(insval,MASK_FABS_D,OP_FABS_D)) || \
> + (is_insn(insval,MASK_FNEG_D,OP_FNEG_D)) || \
> + (is_insn(insval,MASK_FLOGB_D,OP_FLOGB_D)) || \
> + (is_insn(insval,MASK_FCLASS_D,OP_FCLASS_D)) || \
> + (is_insn(insval,MASK_FSQRT_D,OP_FSQRT_D)) || \
> + (is_insn(insval,MASK_FRECIP_D,OP_FRECIP_D)) || \
> + (is_insn(insval,MASK_FRSQRT_D,OP_FRSQRT_D)) || \
> + (is_insn(insval,MASK_FRECIPE_D,OP_FRECIPE_D)) || \
> + (is_insn(insval,MASK_FRSQRTE_D,OP_FRSQRTE_D)) || \
> + (is_insn(insval,MASK_FMOV_D,OP_FMOV_D)) || \
> + (is_insn(insval,MASK_MOVGR2FR_D,OP_MOVGR2FR_D)) || \
> + (is_insn(insval,MASK_FCVT_S_D,OP_FCVT_S_D)) || \
> + (is_insn(insval,MASK_FCVT_D_S,OP_FCVT_D_S)) || \
> + (is_insn(insval,MASK_FTINTRM_W_D,OP_FTINTRM_W_D)) || \
> + (is_insn(insval,MASK_FTINTRM_L_D,OP_FTINTRM_L_D)) || \
> + (is_insn(insval,MASK_FTINTRP_W_D,OP_FTINTRP_W_D)) || \
> + (is_insn(insval,MASK_FTINTRP_L_D,OP_FTINTRP_L_D)) || \
> + (is_insn(insval,MASK_FTINTRZ_W_D,OP_FTINTRZ_W_D)) || \
> + (is_insn(insval,MASK_FTINTRZ_L_D,OP_FTINTRZ_L_D)) || \
> + (is_insn(insval,MASK_FTINTRNE_W_D,OP_FTINTRNE_W_D)) || \
> + (is_insn(insval,MASK_FTINTRNE_L_D,OP_FTINTRNE_L_D)) || \
> + (is_insn(insval,MASK_FTINT_W_D,OP_FTINT_W_D)) || \
> + (is_insn(insval,MASK_FTINT_L_D,OP_FTINT_L_D)) || \
> + (is_insn(insval,MASK_FFINT_D_W,OP_FFINT_D_W)) || \
> + (is_insn(insval,MASK_FFINT_D_L,OP_FFINT_D_L)) || \
> + (is_insn(insval,MASK_FRINT_D,OP_FRINT_D)) || \
> + (is_insn(insval,MASK_FMADD_S,OP_FMADD_S)) || \
> + (is_insn(insval,MASK_FMSUB_S,OP_FMSUB_S)) || \
> + (is_insn(insval,MASK_FNMADD_S,OP_FNMADD_S)) || \
> + (is_insn(insval,MASK_FNMSUB_S,OP_FNMSUB_S)) || \
> + (is_insn(insval,MASK_FMADD_D,OP_FMADD_D)) || \
> + (is_insn(insval,MASK_FMSUB_D,OP_FMSUB_D)) || \
> + (is_insn(insval,MASK_FNMADD_D,OP_FNMADD_D)) || \
> + (is_insn(insval,MASK_FNMSUB_D,OP_FNMSUB_D)) || \
> + (is_insn(insval,MASK_FLD_S,OP_FLD_S)) || \
> + (is_insn(insval,MASK_FLD_D,OP_FLD_D)) || \
> + (is_insn(insval,MASK_FLDX_S,OP_FLDX_S)) || \
> + (is_insn(insval,MASK_FLDX_D,OP_FLDX_D)))
> +
> +#define is_mov2cf_insn(insval) \
> + ((is_insn(insval,MASK_MOVFR2CF,OP_MOVFR2CF)) || \
> + (is_insn(insval,MASK_MOVGR2CF,OP_MOVGR2CF)))
> +
> +#define is_movgr2fcsr_insn(insval) \
> + (is_insn(insval,MASK_MOVGR2FCSR,OP_MOVGR2FCSR))
> +
> +
> +#define is_stb_insn(insval) (is_insn(insval,MASK_ST_B,OP_ST_B))
> +#define is_sth_insn(insval) (is_insn(insval,MASK_ST_H,OP_ST_H))
> +#define is_stw_insn(insval) (is_insn(insval,MASK_ST_W,OP_ST_W))
> +#define is_std_insn(insval) (is_insn(insval,MASK_ST_D,OP_ST_D))
> +#define is_stptrw_insn(insval) (is_insn(insval,MASK_STPTR_W,OP_STPTR_W))
> +#define is_stptrd_insn(insval) (is_insn(insval,MASK_STPTR_D,OP_STPTR_D))
> +#define is_scw_insn(insval) (is_insn(insval,MASK_SC_W,OP_SC_W))
> +#define is_scd_insn(insval) (is_insn(insval,MASK_SC_D,OP_SC_D))
> +#define is_fsts_insn(insval) (is_insn(insval,MASK_FST_S,OP_FST_S))
> +#define is_fstd_insn(insval) (is_insn(insval,MASK_FST_D,OP_FST_D))
> +#define is_fstxs_insn(insval) (is_insn(insval,MASK_FSTX_S,OP_FSTX_S))
> +#define is_fstxd_insn(insval) (is_insn(insval,MASK_FSTX_D,OP_FSTX_D))
> +#define is_stxb_insn(insval) (is_insn(insval,MASK_STX_B,OP_STX_B))
> +#define is_stxh_insn(insval) (is_insn(insval,MASK_STX_H,OP_STX_H))
> +#define is_stxw_insn(insval) (is_insn(insval,MASK_STX_W,OP_STX_W))
> +#define is_stxd_insn(insval) (is_insn(insval,MASK_STX_D,OP_STX_D))
> +#define is_vst_insn(insval) (is_insn(insval,MASK_VST,OP_VST))
> +#define is_xvst_insn(insval) (is_insn(insval,MASK_XVST,OP_XVST))
> +
> +#define is_store_insn(insval) \
> + ((is_stb_insn(insval)) || \
> + (is_sth_insn(insval)) || \
> + (is_stw_insn(insval)) || \
> + (is_std_insn(insval)) || \
> + (is_stptrw_insn(insval)) || \
> + (is_stptrd_insn(insval)) || \
> + (is_scw_insn(insval)) || \
> + (is_scd_insn(insval)) || \
> + (is_fsts_insn(insval)) || \
> + (is_fstd_insn(insval)) || \
> + (is_stxb_insn(insval)) || \
> + (is_stxh_insn(insval)) || \
> + (is_stxw_insn(insval)) || \
> + (is_stxd_insn(insval)) || \
> + (is_vst_insn(insval)) || \
> + (is_xvst_insn(insval)))
> +
> +#define is_am_insn(insval) \
> + ((is_insn(insval,MASK_AMSWAP_W,OP_AMSWAP_W)) || \
> + (is_insn(insval,MASK_AMSWAP_D,OP_AMSWAP_D)) || \
> + (is_insn(insval,MASK_AMADD_W,OP_AMADD_W)) || \
> + (is_insn(insval,MASK_AMADD_D,OP_AMADD_D)) || \
> + (is_insn(insval,MASK_AMAND_W,OP_AMAND_W)) || \
> + (is_insn(insval,MASK_AMAND_D,OP_AMAND_D)) || \
> + (is_insn(insval,MASK_AMOR_W,OP_AMOR_W)) || \
> + (is_insn(insval,MASK_AMOR_D,OP_AMOR_D)) || \
> + (is_insn(insval,MASK_AMXOR_W,OP_AMXOR_W)) || \
> + (is_insn(insval,MASK_AMXOR_D,OP_AMXOR_D)) || \
> + (is_insn(insval,MASK_AMMAX_W,OP_AMMAX_W)) || \
> + (is_insn(insval,MASK_AMMAX_D,OP_AMMAX_D)) || \
> + (is_insn(insval,MASK_AMMIN_W,OP_AMMIN_W)) || \
> + (is_insn(insval,MASK_AMMIN_D,OP_AMMIN_D)) || \
> + (is_insn(insval,MASK_AMMAX_WU,OP_AMMAX_WU)) || \
> + (is_insn(insval,MASK_AMMAX_DU,OP_AMMAX_DU)) || \
> + (is_insn(insval,MASK_AMMIN_WU,OP_AMMIN_WU)) || \
> + (is_insn(insval,MASK_AMMIN_DU,OP_AMMIN_DU)) || \
> + (is_insn(insval,MASK_AMSWAP_DB_W,OP_AMSWAP_DB_W)) || \
> + (is_insn(insval,MASK_AMSWAP_DB_D,OP_AMSWAP_DB_D)) || \
> + (is_insn(insval,MASK_AMADD_DB_W,OP_AMADD_DB_W)) || \
> + (is_insn(insval,MASK_AMADD_DB_D,OP_AMADD_DB_D)) || \
> + (is_insn(insval,MASK_AMAND_DB_W,OP_AMAND_DB_W)) || \
> + (is_insn(insval,MASK_AMAND_DB_D,OP_AMAND_DB_D)) || \
> + (is_insn(insval,MASK_AMOR_DB_W,OP_AMOR_DB_W)) || \
> + (is_insn(insval,MASK_AMOR_DB_D,OP_AMOR_DB_D)) || \
> + (is_insn(insval,MASK_AMXOR_DB_W,OP_AMXOR_DB_W)) || \
> + (is_insn(insval,MASK_AMXOR_DB_D,OP_AMXOR_DB_D)) || \
> + (is_insn(insval,MASK_AMMAX_DB_W,OP_AMMAX_DB_W)) || \
> + (is_insn(insval,MASK_AMMAX_DB_D,OP_AMMAX_DB_D)) || \
> + (is_insn(insval,MASK_AMMIN_DB_W,OP_AMMIN_DB_W)) || \
> + (is_insn(insval,MASK_AMMIN_DB_D,OP_AMMIN_DB_D)) || \
> + (is_insn(insval,MASK_AMMAX_DB_WU,OP_AMMAX_DB_WU)) || \
> + (is_insn(insval,MASK_AMMAX_DB_DU,OP_AMMAX_DB_DU)) || \
> + (is_insn(insval,MASK_AMMIN_DB_WU,OP_AMMIN_DB_WU)) || \
> + (is_insn(insval,MASK_AMMIN_DB_DU,OP_AMMIN_DB_DU)))
> +
> +
> +#define is_cond_load_insn(insval) \
> + ((is_insn(insval,MASK_LDGT_B,OP_LDGT_B)) || \
> + (is_insn(insval,MASK_LDGT_H,OP_LDGT_H)) || \
> + (is_insn(insval,MASK_LDGT_W,OP_LDGT_W)) || \
> + (is_insn(insval,MASK_LDGT_D,OP_LDGT_D)) || \
> + (is_insn(insval,MASK_LDLE_B,OP_LDLE_B)) || \
> + (is_insn(insval,MASK_LDLE_H,OP_LDLE_H)) || \
> + (is_insn(insval,MASK_LDLE_W,OP_LDLE_W)) || \
> + (is_insn(insval,MASK_LDLE_D,OP_LDLE_D)) || \
> + (is_insn(insval,MASK_FLDGT_S,OP_FLDGT_S)) || \
> + (is_insn(insval,MASK_FLDLE_S,OP_FLDLE_S)) || \
> + (is_insn(insval,MASK_FLDGT_D,OP_FLDGT_D)) || \
> + (is_insn(insval,MASK_FLDLE_D,OP_FLDLE_D)))
> +
> +#define is_cond_store_insn(insval) \
> + ((is_insn(insval,MASK_STGT_B,OP_STGT_B)) || \
> + (is_insn(insval,MASK_STGT_H,OP_STGT_H)) || \
> + (is_insn(insval,MASK_STGT_W,OP_STGT_W)) || \
> + (is_insn(insval,MASK_STGT_D,OP_STGT_D)) || \
> + (is_insn(insval,MASK_STLE_B,OP_STLE_B)) || \
> + (is_insn(insval,MASK_STLE_H,OP_STLE_H)) || \
> + (is_insn(insval,MASK_STLE_W,OP_STLE_W)) || \
> + (is_insn(insval,MASK_STLE_D,OP_STLE_D)) || \
> + (is_insn(insval,MASK_FSTGT_S,OP_FSTGT_S)) || \
> + (is_insn(insval,MASK_FSTLE_S,OP_FSTLE_S)) || \
> + (is_insn(insval,MASK_FSTGT_D,OP_FSTGT_D)) || \
> + (is_insn(insval,MASK_FSTLE_D,OP_FSTLE_D)))
> +
> +#define is_ldgt_insn(insval) \
> + ((is_insn(insval,MASK_LDGT_B,OP_LDGT_B)) || \
> + (is_insn(insval,MASK_LDGT_H,OP_LDGT_H)) || \
> + (is_insn(insval,MASK_LDGT_W,OP_LDGT_W)) || \
> + (is_insn(insval,MASK_LDGT_D,OP_LDGT_D)))
> +
> +#define is_ldle_insn(insval) \
> + ((is_insn(insval,MASK_LDLE_B,OP_LDLE_B)) || \
> + (is_insn(insval,MASK_LDLE_H,OP_LDLE_H)) || \
> + (is_insn(insval,MASK_LDLE_W,OP_LDLE_W)) || \
> + (is_insn(insval,MASK_LDLE_D,OP_LDLE_D)))
> +
> +#define is_fldgt_insn(insval) \
> + ((is_insn(insval,MASK_FLDGT_S,OP_FLDGT_S)) || \
> + (is_insn(insval,MASK_FLDGT_D,OP_FLDGT_D)))
> +
> +#define is_fldle_insn(insval) \
> + ((is_insn(insval,MASK_FLDLE_S,OP_FLDLE_S)) || \
> + (is_insn(insval,MASK_FLDLE_D,OP_FLDLE_D)))
> +
> +
> +#define is_stgt_insn(insval) \
> + ((is_insn(insval,MASK_STGT_B,OP_STGT_B)) || \
> + (is_insn(insval,MASK_STGT_H,OP_STGT_H)) || \
> + (is_insn(insval,MASK_STGT_W,OP_STGT_W)) || \
> + (is_insn(insval,MASK_STGT_D,OP_STGT_D)))
> +
> +#define is_stle_insn(insval) \
> + ((is_insn(insval,MASK_STLE_B,OP_STLE_B)) || \
> + (is_insn(insval,MASK_STLE_H,OP_STLE_H)) || \
> + (is_insn(insval,MASK_STLE_W,OP_STLE_W)) || \
> + (is_insn(insval,MASK_STLE_D,OP_STLE_D)))
> +
> +#define is_fstgt_insn(insval) \
> + ((is_insn(insval,MASK_FSTGT_S,OP_FSTGT_S)) || \
> + (is_insn(insval,MASK_FSTGT_D,OP_FSTGT_D)))
> +
> +#define is_fstle_insn(insval) \
> + ((is_insn(insval,MASK_FSTLE_S,OP_FSTLE_S)) || \
> + (is_insn(insval,MASK_FSTLE_D,OP_FSTLE_D)))
> +
> +#define is_jirl_insn(insval) (is_insn(insval,MASK_JIRL,OP_JIRL))
> +#define is_bl_insn(insval) (is_insn(insval,MASK_BL,OP_BL))
> +
> +#define is_jump_insn(insval) \
> + ((is_insn(insval,MASK_BEQZ,OP_BEQZ)) || \
> + (is_insn(insval,MASK_BNEZ,OP_BNEZ)) || \
> + (is_insn(insval,MASK_JIRL,OP_JIRL)) || \
> + (is_insn(insval,MASK_B,OP_B)) || \
> + (is_insn(insval,MASK_BL,OP_BL)) || \
> + (is_insn(insval,MASK_BEQ,OP_BEQ)) || \
> + (is_insn(insval,MASK_BNE,OP_BNE)) || \
> + (is_insn(insval,MASK_BLT,OP_BLT)) || \
> + (is_insn(insval,MASK_BGE,OP_BGE)) || \
> + (is_insn(insval,MASK_BLTU,OP_BLTU)) || \
> + (is_insn(insval,MASK_BGEU,OP_BGEU)))
> +
> +#define is_special_insn(insval) \
> + ((is_insn(insval,MASK_CACOP,OP_CACOP)) || \
> + (is_insn(insval,MASK_TLBCLR,OP_TLBCLR)) || \
> + (is_insn(insval,MASK_TLBFLUSH,OP_TLBFLUSH)) || \
> + (is_insn(insval,MASK_TLBWR,OP_TLBWR)) || \
> + (is_insn(insval,MASK_TLBFILL,OP_TLBFILL)) || \
> + (is_insn(insval,MASK_IDLE,OP_IDLE)) || \
> + (is_insn(insval,MASK_INVTLB,OP_INVTLB)) || \
> + (is_insn(insval,MASK_PRELD,OP_PRELD)) || \
> + (is_insn(insval,MASK_PRELDX,OP_PRELDX)) || \
> + (is_insn(insval,MASK_DBAR,OP_DBAR)) || \
> + (is_insn(insval,MASK_IBAR,OP_IBAR)) || \
> + (is_fcmpcond_insn(insval)))
> +
> +#define is_fcmpcond_insn(insval) \
> + ((is_insn(insval,MASK_FCMP_CAF_S,OP_FCMP_CAF_S)) || \
> + (is_insn(insval,MASK_FCMP_SAF_S,OP_FCMP_SAF_S)) || \
> + (is_insn(insval,MASK_FCMP_CLT_S,OP_FCMP_CLT_S)) || \
> + (is_insn(insval,MASK_FCMP_SLT_S,OP_FCMP_SLT_S)) || \
> + (is_insn(insval,MASK_FCMP_SGT_S,OP_FCMP_SGT_S)) || \
> + (is_insn(insval,MASK_FCMP_CEQ_S,OP_FCMP_CEQ_S)) || \
> + (is_insn(insval,MASK_FCMP_SEQ_S,OP_FCMP_SEQ_S)) || \
> + (is_insn(insval,MASK_FCMP_CLE_S,OP_FCMP_CLE_S)) || \
> + (is_insn(insval,MASK_FCMP_SLE_S,OP_FCMP_SLE_S)) || \
> + (is_insn(insval,MASK_FCMP_SGE_S,OP_FCMP_SGE_S)) || \
> + (is_insn(insval,MASK_FCMP_CUN_S,OP_FCMP_CUN_S)) || \
> + (is_insn(insval,MASK_FCMP_SUN_S,OP_FCMP_SUN_S)) || \
> + (is_insn(insval,MASK_FCMP_CULT_S,OP_FCMP_CULT_S)) || \
> + (is_insn(insval,MASK_FCMP_CUGT_S,OP_FCMP_CUGT_S)) || \
> + (is_insn(insval,MASK_FCMP_SULT_S,OP_FCMP_SULT_S)) || \
> + (is_insn(insval,MASK_FCMP_CUEQ_S,OP_FCMP_CUEQ_S)) || \
> + (is_insn(insval,MASK_FCMP_SUEQ_S,OP_FCMP_SUEQ_S)) || \
> + (is_insn(insval,MASK_FCMP_CULE_S,OP_FCMP_CULE_S)) || \
> + (is_insn(insval,MASK_FCMP_CUGE_S,OP_FCMP_CUGE_S)) || \
> + (is_insn(insval,MASK_FCMP_SULE_S,OP_FCMP_SULE_S)) || \
> + (is_insn(insval,MASK_FCMP_CNE_S,OP_FCMP_CNE_S)) || \
> + (is_insn(insval,MASK_FCMP_SNE_S,OP_FCMP_SNE_S)) || \
> + (is_insn(insval,MASK_FCMP_COR_S,OP_FCMP_COR_S)) || \
> + (is_insn(insval,MASK_FCMP_SOR_S,OP_FCMP_SOR_S)) || \
> + (is_insn(insval,MASK_FCMP_CUNE_S,OP_FCMP_CUNE_S)) || \
> + (is_insn(insval,MASK_FCMP_SUNE_S,OP_FCMP_SUNE_S)) || \
> + (is_insn(insval,MASK_FCMP_CAF_D,OP_FCMP_CAF_D)) || \
> + (is_insn(insval,MASK_FCMP_SAF_D,OP_FCMP_SAF_D)) || \
> + (is_insn(insval,MASK_FCMP_CLT_D,OP_FCMP_CLT_D)) || \
> + (is_insn(insval,MASK_FCMP_SLT_D,OP_FCMP_SLT_D)) || \
> + (is_insn(insval,MASK_FCMP_SGT_D,OP_FCMP_SGT_D)) || \
> + (is_insn(insval,MASK_FCMP_CEQ_D,OP_FCMP_CEQ_D)) || \
> + (is_insn(insval,MASK_FCMP_SEQ_D,OP_FCMP_SEQ_D)) || \
> + (is_insn(insval,MASK_FCMP_CLE_D,OP_FCMP_CLE_D)) || \
> + (is_insn(insval,MASK_FCMP_SLE_D,OP_FCMP_SLE_D)) || \
> + (is_insn(insval,MASK_FCMP_SGE_D,OP_FCMP_SGE_D)) || \
> + (is_insn(insval,MASK_FCMP_CUN_D,OP_FCMP_CUN_D)) || \
> + (is_insn(insval,MASK_FCMP_SUN_D,OP_FCMP_SUN_D)) || \
> + (is_insn(insval,MASK_FCMP_CULT_D,OP_FCMP_CULT_D)) || \
> + (is_insn(insval,MASK_FCMP_CUGT_D,OP_FCMP_CUGT_D)) || \
> + (is_insn(insval,MASK_FCMP_SULT_D,OP_FCMP_SULT_D)) || \
> + (is_insn(insval,MASK_FCMP_CUEQ_D,OP_FCMP_CUEQ_D)) || \
> + (is_insn(insval,MASK_FCMP_SUEQ_D,OP_FCMP_SUEQ_D)) || \
> + (is_insn(insval,MASK_FCMP_CULE_D,OP_FCMP_CULE_D)) || \
> + (is_insn(insval,MASK_FCMP_CUGE_D,OP_FCMP_CUGE_D)) || \
> + (is_insn(insval,MASK_FCMP_SULE_D,OP_FCMP_SULE_D)) || \
> + (is_insn(insval,MASK_FCMP_CNE_D,OP_FCMP_CNE_D)) || \
> + (is_insn(insval,MASK_FCMP_SNE_D,OP_FCMP_SNE_D)) || \
> + (is_insn(insval,MASK_FCMP_COR_D,OP_FCMP_COR_D)) || \
> + (is_insn(insval,MASK_FCMP_SOR_D,OP_FCMP_SOR_D)) || \
> + (is_insn(insval,MASK_FCMP_CUNE_D,OP_FCMP_CUNE_D)) || \
> + (is_insn(insval,MASK_FCMP_SUNE_D,OP_FCMP_SUNE_D)))
> +
> +#endif /* ARCH_LOONGARCH_INSN_H */
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support
2024-11-13 9:53 ` [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support Hui Li
@ 2024-11-13 12:41 ` Guinevere Larsen
2024-11-14 17:23 ` Guinevere Larsen
2024-11-19 13:20 ` Hui Li
0 siblings, 2 replies; 13+ messages in thread
From: Guinevere Larsen @ 2024-11-13 12:41 UTC (permalink / raw)
To: Hui Li, gdb-patches; +Cc: Tiezhu Yang
On 11/13/24 6:53 AM, Hui Li wrote:
> GDB provides a special process record and replay target that can
> record a log of the process execution, and replay it later with
> both forward and reverse execution commands. This patch adds the
> basic support of process record and replay on LoongArch, it allows
> users to debug basic LoongArch instructions and provides reverse
> debugging support.
>
> Here is a simple example on LoongArch:
>
> $ cat test.c
> int a = 0;
> int main()
> {
> a = 1;
> a = 2;
> return 0;
> }
> $ gdb test
> ...
> (gdb) start
> ...
> Temporary breakpoint 1, main () at test.c:4
> 4 a = 1;
> (gdb) record
> (gdb) p a
> $1 = 0
> (gdb) n
> 5 a = 2;
> (gdb) n
> 6 return 0;
> (gdb) p a
> $2 = 2
> (gdb) rn
> 5 a = 2;
> (gdb) rn
>
> Reached end of recorded history; stopping.
> Backward execution from here not possible.
> main () at test.c:4
> 4 a = 1;
> (gdb) p a
> $3 = 0
> (gdb) record stop
> Process record is stopped and all execution logs are deleted.
> (gdb) c
> Continuing.
> [Inferior 1 (process 129178) exited normally]
>
> Signed-off-by: Hui Li <lihui@loongson.cn>
Hi! Thanks for doing this! More architectures supporting reverse
debugging is always welcome :)
I do have some comments on the patch as it is right now.
> ---
> gdb/configure.tgt | 2 +-
> gdb/loongarch-linux-tdep.c | 3 +
> gdb/loongarch-tdep.c | 592 +++++++++++++++++++++++++++++++++++++
> gdb/loongarch-tdep.h | 3 +
> gdb/testsuite/lib/gdb.exp | 2 +
> 5 files changed, 601 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
> index 62df71b13fa..2d78c1182fa 100644
> --- a/gdb/configure.tgt
> +++ b/gdb/configure.tgt
> @@ -363,7 +363,7 @@ lm32-*-*)
> loongarch*-*-linux*)
> # Target: LoongArch running Linux
> gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
> - linux-tdep.o solib-svr4.o"
> + linux-tdep.o solib-svr4.o linux-record.o"
> ;;
>
> m32c-*-*)
> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
> index 71578060303..86e7ed8a0bc 100644
> --- a/gdb/loongarch-linux-tdep.c
> +++ b/gdb/loongarch-linux-tdep.c
> @@ -602,6 +602,9 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Get the syscall number from the arch's register. */
> set_gdbarch_get_syscall_number (gdbarch, loongarch_linux_get_syscall_number);
> +
> + /* Reversible debugging, process record. */
> + set_gdbarch_process_record (gdbarch, loongarch_process_record);
> }
>
> /* Initialize LoongArch Linux target support. */
> diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
> index c50dd7f4b78..cf72c48b573 100644
> --- a/gdb/loongarch-tdep.c
> +++ b/gdb/loongarch-tdep.c
> @@ -18,12 +18,16 @@
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> #include "arch-utils.h"
> +#include "arch/loongarch-insn.h"
> #include "dwarf2/frame.h"
> #include "elf-bfd.h"
> #include "extract-store-integer.h"
> #include "frame-unwind.h"
> #include "gdbcore.h"
> +#include "linux-record.h"
> #include "loongarch-tdep.h"
> +#include "record.h"
> +#include "record-full.h"
> #include "reggroups.h"
> #include "target.h"
> #include "target-descriptions.h"
> @@ -1889,6 +1893,594 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> return gdbarch;
> }
>
> +/* LoongArch process record-replay related structures, defines etc. */
> +
> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct loongarch_mem_r, mem_len); \
> + memcpy(&MEMS->len, &RECORD_BUF[0], \
> + sizeof(struct loongarch_mem_r) * LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +/* LoongArch record/replay structures and enumerations. */
> +
> +struct loongarch_mem_r
> +{
> + uint64_t len; /* Record length. */
> + uint64_t addr; /* Memory address. */
> +};
> +
> +enum loongarch_record_result
> +{
> + LOONGARCH_RECORD_SUCCESS,
> + LOONGARCH_RECORD_UNSUPPORTED,
> + LOONGARCH_RECORD_UNKNOWN
> +};
> +
> +struct loongarch_insn_record
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Addr of insn to be recorded. */
> + uint32_t insn; /* Insn to be recorded. */
> + uint32_t mem_rec_count; /* Count of memory records. */
> + uint32_t reg_rec_count; /* Count of register records. */
> + uint32_t *regs; /* Registers to be recorded. */
> + struct loongarch_mem_r *loongarch_mems; /* Memory location to be recorded. */
> +};
Record-full is already infamous for being quite slow, and a significant
part of it is due to dynamic memory allocation and reading inferior
state (memory or registers). Your strategy here is doubling up the
number of both allocations and accesses to the inferior. The code would
perform much better if you just did the calls to the record-full
functions instead of building it here first.
Did you run into any troubles with that traditional approach that led
you to design this strategy?
> +
> +/* Record handler for data processing instructions. */
> +
> +static unsigned int
> +loongarch_record_data_proc_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int rd;
> + uint32_t record_buf[1];
> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + record_buf[0] = rd;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for read time instructions. */
> +
> +static unsigned int
> +loongarch_record_read_time_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int rd, rj;
> + uint32_t record_buf[2];
> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + rj = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + record_buf[0] = rd;
> + record_buf[1] = rj;
> + loongarch_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for jump instructions. */
> +
> +static unsigned int
> +loongarch_record_jump_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + if (is_jirl_insn (loongarch_insn_r->insn))
> + {
> + int rd;
> + uint32_t record_buf[1];
> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + record_buf[0] = rd;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> + }
> + else if(is_bl_insn (loongarch_insn_r->insn))
> + {
> + uint32_t record_buf[1];
> + record_buf[0] = LOONGARCH_RA_REGNUM;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> + }
> +
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for float data processing instructions. */
> +
> +static unsigned int
> +loongarch_record_float_data_proc_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int fd;
> + uint32_t record_buf[1];
> + fd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
> + + LOONGARCH_FIRST_FP_REGNUM;
> + record_buf[0] = fd;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for fcsr processing instructions. */
> +
> +static unsigned int
> +loongarch_record_fcsr_proc_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int fcsr;
> + uint32_t record_buf[1];
> + fcsr = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
> + + LOONGARCH_FCSR_REGNUM;
> + record_buf[0] = fcsr;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for condition flag register processing instructions. */
> +
> +static unsigned int
> +loongarch_record_fcc_proc_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int cd, imm3_4;
> + uint32_t record_buf[1];
> + cd = loongarch_decode_imm ("0:3", loongarch_insn_r->insn, 0);
> + imm3_4 = loongarch_decode_imm ("3:2", loongarch_insn_r->insn, 0);
> + if (imm3_4 != 0)
> + return LOONGARCH_RECORD_UNSUPPORTED;
> +
> + record_buf[0] = cd;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for float instructions. */
> +
> +static unsigned int
> +loongarch_record_float_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + if (is_movgr2fcsr_insn (loongarch_insn_r->insn))
> + return loongarch_record_fcsr_proc_insn (loongarch_insn_r);
> + else if (is_mov2cf_insn (loongarch_insn_r->insn))
> + return loongarch_record_fcc_proc_insn (loongarch_insn_r);
> + else
> + return loongarch_record_float_data_proc_insn (loongarch_insn_r);
> +}
> +
> +/* Record handler for store instructions. */
> +
> +static unsigned int
> +loongarch_record_store_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + enum store_types
> + {
> + STB, STH, STW, STD, STXB, STXH, STXW, STXD, STPTRW, STPTRD,
> + SCW, SCD, FSTS, FSTD, FSTXS, FSTXD, VST, XVST, NOT_STORE
> + };
> + int store_type;
> + uint64_t record_buf_mem[2];
> + store_type = is_stb_insn (loongarch_insn_r->insn) ? STB :
> + is_sth_insn (loongarch_insn_r->insn) ? STH :
> + is_stw_insn (loongarch_insn_r->insn) ? STW :
> + is_std_insn (loongarch_insn_r->insn) ? STD :
> + is_stxb_insn (loongarch_insn_r->insn) ? STXB :
> + is_stxh_insn (loongarch_insn_r->insn) ? STXH :
> + is_stxw_insn (loongarch_insn_r->insn) ? STXW :
> + is_stxd_insn (loongarch_insn_r->insn) ? STXD :
> + is_stptrw_insn (loongarch_insn_r->insn) ? STPTRW :
> + is_stptrd_insn (loongarch_insn_r->insn) ? STPTRD :
> + is_scw_insn (loongarch_insn_r->insn) ? SCW :
> + is_scd_insn (loongarch_insn_r->insn) ? SCD :
> + is_fsts_insn (loongarch_insn_r->insn) ? FSTS :
> + is_fstd_insn (loongarch_insn_r->insn) ? FSTD :
> + is_fstxs_insn (loongarch_insn_r->insn) ? FSTXS :
> + is_fstxd_insn (loongarch_insn_r->insn) ? FSTXD :
> + is_vst_insn (loongarch_insn_r->insn) ? VST :
> + is_xvst_insn (loongarch_insn_r->insn) ? XVST :
> + NOT_STORE;
> +
> + if (store_type == STB || store_type == STH || store_type == STW
> + || store_type == STD || store_type == FSTS || store_type == FSTD
> + || store_type == VST || store_type == XVST)
> + {
> + int rj_num;
> + int data_size;
> + int imm;
> + uint64_t rj_val;
> + uint64_t address;
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + imm = loongarch_decode_imm ("10:12", loongarch_insn_r->insn, 1);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
> + address = rj_val + imm;
> + switch (store_type)
> + {
> + case STB:
> + data_size = 1;
> + break;
> + case STH:
> + data_size = 2;
> + break;
> + case STW:
> + case FSTS:
> + data_size = 4;
> + break;
> + case STD:
> + case FSTD:
> + data_size = 8;
> + break;
> + case VST:
> + data_size = 16;
> + break;
> + case XVST:
> + data_size = 32;
> + break;
> + default:
> + data_size = 0;
> + break;
> + }
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = address;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
> + loongarch_insn_r->mem_rec_count, record_buf_mem);
> + return LOONGARCH_RECORD_SUCCESS;
> + }
> + else if (store_type == STXB || store_type == STXH || store_type == STXW
> + || store_type == STXD || store_type == FSTXS || store_type == FSTXD)
> + {
> + int data_size;
> + int rj_num, rk_num;
> + uint64_t rj_val,rk_val;
> + uint64_t address;
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
> + address = rj_val + rk_val;
> + switch (store_type)
> + {
> + case STXB:
> + data_size = 1;
> + break;
> + case STXH:
> + data_size = 2;
> + break;
> + case STXW:
> + case FSTXS:
> + data_size = 4;
> + break;
> + case STXD:
> + case FSTXD:
> + data_size = 8;
> + break;
> + default:
> + data_size = 0;
> + break;
> + }
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = address;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
> + loongarch_insn_r->mem_rec_count, record_buf_mem);
> +
> + return LOONGARCH_RECORD_SUCCESS;
> + }
> + else if (store_type == STPTRW || store_type == STPTRD || store_type == SCW
> + || store_type == SCD)
> + {
> + int data_size;
> + int rj_num;
> + int imm;
> + uint64_t rj_val;
> + uint64_t address;
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + imm = loongarch_decode_imm ("10:14<<2",
> + loongarch_insn_r->insn, 1);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
> + address = rj_val + imm;
> + switch (store_type)
> + {
> + case STPTRW:
> + case SCW:
> + data_size = 4;
> + break;
> + case STPTRD:
> + case SCD:
> + data_size = 8;
> + break;
> + default:
> + data_size = 0;
> + break;
> + }
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = address;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
> + loongarch_insn_r->mem_rec_count, record_buf_mem);
> + return LOONGARCH_RECORD_SUCCESS;
> + }
> +
> + return LOONGARCH_RECORD_UNSUPPORTED;
> +}
> +
> +/* Record handler for atomic memory access instructions. */
> +
> +static unsigned int
> +loongarch_record_am_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int rj_num, rd_num;
> + int word_or_double;
> + int data_size;
> + uint64_t address;
> + uint32_t record_buf[1];
> + uint64_t record_buf_mem[2];
> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + word_or_double = loongarch_decode_imm ("15:1",
> + loongarch_insn_r->insn, 0);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &address);
> + data_size = word_or_double == 1 ? 8 : 4;
> + record_buf[0] = rd_num;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = address;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems, loongarch_insn_r->mem_rec_count,
> + record_buf_mem);
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for condition load instructions. */
> +
> +static unsigned int
> +loongarch_record_cond_load_insn (loongarch_insn_record *loongarch_insn_r)
> + {
> + int rd_num, rj_num, rk_num, fd_num;
> + uint64_t rj_val, rk_val;
> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + fd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
> +
> + if ((is_ldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
> + || (is_ldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
> + {
> + uint32_t record_buf[1];
> + record_buf[0] = rd_num;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + }
> + else if ((is_fldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
> + || (is_fldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
> + {
> + uint32_t record_buf[1];
> + record_buf[0] = fd_num;
> + loongarch_insn_r->reg_rec_count = 1;
> +
> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
> + record_buf);
> + }
> +
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for condition store instructions. */
> +
> +static unsigned int
> +loongarch_record_cond_store_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + int rj_num, rk_num;
> + int data_size;
> + uint64_t rj_val, rk_val;
> + uint32_t length_opcode;
> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num, &rj_val);
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num, &rk_val);
> +
> + if ((is_stgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
> + || (is_stle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
> + {
> + uint64_t record_buf_mem[2];
> + length_opcode = loongarch_insn_r->insn & 0x00018000;
> + switch (length_opcode)
> + {
> + case 0x00000000:
> + data_size = 1;
> + break;
> + case 0x00008000:
> + data_size = 2;
> + break;
> + case 0x00010000:
> + data_size = 4;
> + break;
> + case 0x00018000:
> + data_size = 8;
> + break;
> + default:
> + data_size = 0;
> + break;
> + }
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = rj_val;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
> + loongarch_insn_r->mem_rec_count, record_buf_mem);
> + }
> + else if ((is_fstgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
> + || (is_fstle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
> + {
> + uint64_t record_buf_mem[2];
> + length_opcode = loongarch_insn_r->insn & 0x00008000;
> + switch (length_opcode)
> + {
> + case 0x00000000:
> + data_size = 4;
> + break;
> + case 0x00008000:
> + data_size = 8;
> + break;
> + default:
> + data_size = 0;
> + break;
> + }
> + record_buf_mem[0] = data_size;
> + record_buf_mem[1] = rj_val;
> + loongarch_insn_r->mem_rec_count = 1;
> +
> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
> + loongarch_insn_r->mem_rec_count,record_buf_mem);
> + }
> +
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for special instructions like privilege instructions,
> + barrier instructions and cache related instructions etc. */
> +
> +static unsigned int
> +loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
> +{
> + return LOONGARCH_RECORD_SUCCESS;
> +}
> +
> +/* Decode insns type and invoke its record handler. */
> +
> +static unsigned int
> +loongarch_record_decode_insn_handler (loongarch_insn_record *loongarch_insn_r)
> +{
> + if (is_data_process_insn (loongarch_insn_r->insn))
> + return loongarch_record_data_proc_insn (loongarch_insn_r);
> + else if (is_jump_insn (loongarch_insn_r->insn))
> + return loongarch_record_jump_insn (loongarch_insn_r);
> + else if (is_store_insn (loongarch_insn_r->insn))
> + return loongarch_record_store_insn (loongarch_insn_r);
> + else if (is_read_time_insn (loongarch_insn_r->insn))
> + return loongarch_record_read_time_insn (loongarch_insn_r);
> + else if (is_float_insn (loongarch_insn_r->insn))
> + return loongarch_record_float_insn (loongarch_insn_r);
> + else if (is_special_insn (loongarch_insn_r->insn))
> + return loongarch_record_special_insn (loongarch_insn_r);
> + else if (is_am_insn (loongarch_insn_r->insn))
> + return loongarch_record_am_insn (loongarch_insn_r);
> + else if (is_cond_load_insn (loongarch_insn_r->insn))
> + return loongarch_record_cond_load_insn (loongarch_insn_r);
> + else if (is_cond_store_insn (loongarch_insn_r->insn))
> + return loongarch_record_cond_store_insn (loongarch_insn_r);
> +
> + return LOONGARCH_RECORD_UNSUPPORTED;
> +}
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to record_arch_list
> + return -1 if something is wrong. */
> +
> +int
> +loongarch_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> + int rec_num = 0;
> + uint32_t ret = 0;
> + loongarch_insn_record loongarch_record;
> +
> + /* reset the content of loongarch_record */
> + memset (&loongarch_record, 0, sizeof (loongarch_insn_record));
> +
> + /* write the loongarch_record */
> + loongarch_record.gdbarch = gdbarch;
> + loongarch_record.regcache = regcache;
> + loongarch_record.this_addr = insn_addr;
> +
> + /* Get the current instruction */
> + loongarch_record.insn = (uint32_t) loongarch_fetch_instruction (insn_addr);
> + ret = loongarch_record_decode_insn_handler (&loongarch_record);
> + if (ret == LOONGARCH_RECORD_UNSUPPORTED)
> + {
> + gdb_printf (gdb_stderr,
> + _("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + loongarch_record.insn,
> + paddress (gdbarch, insn_addr));
When dealing with unsupported instructions, at least in x86, we use
error, rather than gdb_printf to stderr. Using errors also ensure that a
partially recorded instruction (which isn't the case yet, but should be)
will be fully released by the caller of this function.
> + ret = -1;
> + }
> + if (ret == LOONGARCH_RECORD_SUCCESS)
> + {
> + /* Record registers. */
> + record_full_arch_list_add_reg (loongarch_record.regcache,
> + LOONGARCH_PC_REGNUM);
> + if (loongarch_record.reg_rec_count)
> + {
> + for (rec_num = 0; rec_num < loongarch_record.reg_rec_count; rec_num++)
> + {
> + if (record_full_arch_list_add_reg (loongarch_record.regcache,
> + loongarch_record.regs[rec_num]))
> + ret = -1;
> + }
> + }
> +
> + /* Record memories. */
> + if (loongarch_record.mem_rec_count)
> + {
> + for (rec_num = 0; rec_num < loongarch_record.mem_rec_count; rec_num++)
> + {
> + if (record_full_arch_list_add_mem
> + ((CORE_ADDR)loongarch_record.loongarch_mems[rec_num].addr,
> + loongarch_record.loongarch_mems[rec_num].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_full_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + return ret;
> +}
> +
> void _initialize_loongarch_tdep ();
> void
> _initialize_loongarch_tdep ()
> diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
> index 5c8108182ad..a148363c795 100644
> --- a/gdb/loongarch-tdep.h
> +++ b/gdb/loongarch-tdep.h
> @@ -44,4 +44,7 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
> CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) = nullptr;
> };
>
> +extern int loongarch_process_record (struct gdbarch *gdbarch,
> + struct regcache *regcache, CORE_ADDR addr);
> +
> #endif /* LOONGARCH_TDEP_H */
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 410f99e3350..9b994a9f640 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -3698,6 +3698,7 @@ proc supports_process_record {} {
> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
> || [istarget "i\[34567\]86-*-linux*"]
> || [istarget "aarch64*-*-linux*"]
> + || [istarget "loongarch*-*-linux*"]
> || [istarget "powerpc*-*-linux*"]
> || [istarget "s390*-*-linux*"] } {
> return 1
> @@ -3717,6 +3718,7 @@ proc supports_reverse {} {
> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
> || [istarget "i\[34567\]86-*-linux*"]
> || [istarget "aarch64*-*-linux*"]
> + || [istarget "loongarch*-*-linux*"]
> || [istarget "powerpc*-*-linux*"]
> || [istarget "s390*-*-linux*"] } {
> return 1
--
Cheers,
Guinevere Larsen
She/Her/Hers
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay
2024-11-13 9:53 ` [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay Hui Li
@ 2024-11-13 13:01 ` Guinevere Larsen
2024-11-19 13:22 ` Hui Li
0 siblings, 1 reply; 13+ messages in thread
From: Guinevere Larsen @ 2024-11-13 13:01 UTC (permalink / raw)
To: Hui Li, gdb-patches; +Cc: Tiezhu Yang
Hi!
Again, I don't understand the loongarch specific parts, so I'll leave
review of those for Tiezhu Yang. I did have a couple of general
suggestions, but with those fixed, I'm happy to approve the reverse
debugging parts of this patch!
Approved-By: Guinevere Larsen <guinevere@redhat.com> (record-full)
On 11/13/24 6:53 AM, Hui Li wrote:
> The process record and replay function also need record Linux
> system call instruction. This patch adds LoongArch system call
> number definitions in gdb/arch/loongarch-syscall.h, and adds
> loongarch_linux_syscall_record() in gdb/loongarch-linux-tdep.c
> to record system call execute log. With this patch, the mainly
> function of process record/replay and reverse debugging has been
typo here. Do you mean "main functions" or "main functionality" ?
> implemented.
>
> The LoongArch system call numbers definitions are obtained from Linux kernel.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h
>
> Signed-off-by: Hui Li <lihui@loongson.cn>
> ---
> gdb/arch/loongarch-syscall.h | 348 +++++++++++++++++++++
> gdb/loongarch-linux-tdep.c | 565 +++++++++++++++++++++++++++++++++++
> gdb/loongarch-tdep.c | 18 ++
> gdb/loongarch-tdep.h | 4 +
> 4 files changed, 935 insertions(+)
> create mode 100644 gdb/arch/loongarch-syscall.h
>
> diff --git a/gdb/arch/loongarch-syscall.h b/gdb/arch/loongarch-syscall.h
> new file mode 100644
> index 00000000000..6f10b1d33e7
> --- /dev/null
> +++ b/gdb/arch/loongarch-syscall.h
> @@ -0,0 +1,348 @@
> +/* Target-dependent code for LoongArch
> +
> + Copyright (C) 2024 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +/* The syscall number definitions are obtained from Linux kernel header file.
> + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
> + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h */
> +
> +#ifndef ARCH_LOONGARCH_SYSCALL_H
> +#define ARCH_LOONGARCH_SYSCALL_H
> +
> +enum loongarch_syscall
> +{
> + loongarch_sys_io_setup = 0,
> + loongarch_sys_io_destroy = 1,
> + loongarch_sys_io_submit = 2,
> + loongarch_sys_io_cancel = 3,
> + loongarch_sys_io_getevents = 4,
> + loongarch_sys_setxattr = 5,
> + loongarch_sys_lsetxattr = 6,
> + loongarch_sys_fsetxattr = 7,
> + loongarch_sys_getxattr = 8,
> + loongarch_sys_lgetxattr = 9,
> + loongarch_sys_fgetxattr = 10,
> + loongarch_sys_listxattr = 11,
> + loongarch_sys_llistxattr = 12,
> + loongarch_sys_flistxattr = 13,
> + loongarch_sys_removexattr = 14,
> + loongarch_sys_lremovexattr = 15,
> + loongarch_sys_fremovexattr = 16,
> + loongarch_sys_getcwd = 17,
> + loongarch_sys_lookup_dcookie = 18,
> + loongarch_sys_eventfd2 = 19,
> + loongarch_sys_epoll_create1 = 20,
> + loongarch_sys_epoll_ctl = 21,
> + loongarch_sys_epoll_pwait = 22,
> + loongarch_sys_dup = 23,
> + loongarch_sys_dup3 = 24,
> + loongarch_sys_fcntl = 25,
> + loongarch_sys_inotify_init1 = 26,
> + loongarch_sys_inotify_add_watch = 27,
> + loongarch_sys_inotify_rm_watch = 28,
> + loongarch_sys_ioctl = 29,
> + loongarch_sys_ioprio_set = 30,
> + loongarch_sys_ioprio_get = 31,
> + loongarch_sys_flock = 32,
> + loongarch_sys_mknodat = 33,
> + loongarch_sys_mkdirat = 34,
> + loongarch_sys_unlinkat = 35,
> + loongarch_sys_symlinkat = 36,
> + loongarch_sys_linkat = 37,
> +
> + loongarch_sys_umount2 = 39,
> + loongarch_sys_mount = 40,
> + loongarch_sys_pivot_root = 41,
> + loongarch_sys_nfsservctl = 42,
> + loongarch_sys_statfs = 43,
> + loongarch_sys_fstatfs = 44,
> + loongarch_sys_truncate = 45,
> + loongarch_sys_ftruncate = 46,
> + loongarch_sys_fallocate = 47,
> + loongarch_sys_faccessat = 48,
> + loongarch_sys_chdir = 49,
> + loongarch_sys_fchdir = 50,
> + loongarch_sys_chroot = 51,
> + loongarch_sys_fchmod = 52,
> + loongarch_sys_fchmodat = 53,
> + loongarch_sys_fchownat = 54,
> + loongarch_sys_fchown = 55,
> + loongarch_sys_openat = 56,
> + loongarch_sys_close = 57,
> + loongarch_sys_vhangup = 58,
> + loongarch_sys_pipe2 = 59,
> + loongarch_sys_quotactl = 60,
> + loongarch_sys_getdents64 = 61,
> + loongarch_sys_lseek = 62,
> + loongarch_sys_read = 63,
> + loongarch_sys_write = 64,
> + loongarch_sys_readv = 65,
> + loongarch_sys_writev = 66,
> + loongarch_sys_pread64 = 67,
> + loongarch_sys_pwrite64 = 68,
> + loongarch_sys_preadv = 69,
> + loongarch_sys_pwritev = 70,
> + loongarch_sys_sendfile = 71,
> + loongarch_sys_pselect6 = 72,
> + loongarch_sys_ppoll = 73,
> + loongarch_sys_signalfd4 = 74,
> + loongarch_sys_vmsplice = 75,
> + loongarch_sys_splice = 76,
> + loongarch_sys_tee = 77,
> + loongarch_sys_readlinkat = 78,
> + loongarch_sys_newfstatat = 79,
> + loongarch_sys_fstat = 80,
> + loongarch_sys_sync = 81,
> + loongarch_sys_fsync = 82,
> + loongarch_sys_fdatasync = 83,
> + loongarch_sys_sync_file_range = 84,
> + loongarch_sys_timerfd_create = 85,
> + loongarch_sys_timerfd_settime = 86,
> + loongarch_sys_timerfd_gettime = 87,
> + loongarch_sys_utimensat = 88,
> + loongarch_sys_acct = 89,
> + loongarch_sys_capget = 90,
> + loongarch_sys_capset = 91,
> + loongarch_sys_personality = 92,
> + loongarch_sys_exit = 93,
> + loongarch_sys_exit_group = 94,
> + loongarch_sys_waitid = 95,
> + loongarch_sys_set_tid_address = 96,
> + loongarch_sys_unshare = 97,
> + loongarch_sys_futex = 98,
> + loongarch_sys_set_robust_list = 99,
> + loongarch_sys_get_robust_list = 100,
> + loongarch_sys_nanosleep = 101,
> + loongarch_sys_getitimer = 102,
> + loongarch_sys_setitimer = 103,
> + loongarch_sys_kexec_load = 104,
> + loongarch_sys_init_module = 105,
> + loongarch_sys_delete_module = 106,
> + loongarch_sys_timer_create = 107,
> + loongarch_sys_timer_gettime = 108,
> + loongarch_sys_timer_getoverrun = 109,
> + loongarch_sys_timer_settime = 110,
> + loongarch_sys_timer_delete = 111,
> + loongarch_sys_clock_settime = 112,
> + loongarch_sys_clock_gettime = 113,
> + loongarch_sys_clock_getres = 114,
> + loongarch_sys_clock_nanosleep = 115,
> + loongarch_sys_syslog = 116,
> + loongarch_sys_ptrace = 117,
> + loongarch_sys_sched_setparam = 118,
> + loongarch_sys_sched_setscheduler = 119,
> + loongarch_sys_sched_getscheduler = 120,
> + loongarch_sys_sched_getparam = 121,
> + loongarch_sys_sched_setaffinity = 122,
> + loongarch_sys_sched_getaffinity = 123,
> + loongarch_sys_sched_yield = 124,
> + loongarch_sys_sched_get_priority_max = 125,
> + loongarch_sys_sched_get_priority_min = 126,
> + loongarch_sys_sched_rr_get_interval = 127,
> + loongarch_sys_restart_syscall = 128,
> + loongarch_sys_kill = 129,
> + loongarch_sys_tkill = 130,
> + loongarch_sys_tgkill = 131,
> + loongarch_sys_sigaltstack = 132,
> + loongarch_sys_rt_sigsuspend = 133,
> + loongarch_sys_rt_sigaction = 134,
> + loongarch_sys_rt_sigprocmask = 135,
> + loongarch_sys_rt_sigpending = 136,
> + loongarch_sys_rt_sigtimedwait = 137,
> + loongarch_sys_rt_sigqueueinfo = 138,
> + loongarch_sys_rt_sigreturn = 139,
> + loongarch_sys_setpriority = 140,
> + loongarch_sys_getpriority = 141,
> + loongarch_sys_reboot = 142,
> + loongarch_sys_setregid = 143,
> + loongarch_sys_setgid = 144,
> + loongarch_sys_setreuid = 145,
> + loongarch_sys_setuid = 146,
> + loongarch_sys_setresuid = 147,
> + loongarch_sys_getresuid = 148,
> + loongarch_sys_setresgid = 149,
> + loongarch_sys_getresgid = 150,
> + loongarch_sys_setfsuid = 151,
> + loongarch_sys_setfsgid = 152,
> + loongarch_sys_times = 153,
> + loongarch_sys_setpgid = 154,
> + loongarch_sys_getpgid = 155,
> + loongarch_sys_getsid = 156,
> + loongarch_sys_setsid = 157,
> + loongarch_sys_getgroups = 158,
> + loongarch_sys_setgroups = 159,
> + loongarch_sys_uname = 160,
> + loongarch_sys_sethostname = 161,
> + loongarch_sys_setdomainname = 162,
> +
> + loongarch_sys_getrusage = 165,
> + loongarch_sys_umask = 166,
> + loongarch_sys_prctl = 167,
> + loongarch_sys_getcpu = 168,
> + loongarch_sys_gettimeofday = 169,
> + loongarch_sys_settimeofday = 170,
> + loongarch_sys_adjtimex = 171,
> + loongarch_sys_getpid = 172,
> + loongarch_sys_getppid = 173,
> + loongarch_sys_getuid = 174,
> + loongarch_sys_geteuid = 175,
> + loongarch_sys_getgid = 176,
> + loongarch_sys_getegid = 177,
> + loongarch_sys_gettid = 178,
> + loongarch_sys_sysinfo = 179,
> + loongarch_sys_mq_open = 180,
> + loongarch_sys_mq_unlink = 181,
> + loongarch_sys_mq_timedsend = 182,
> + loongarch_sys_mq_timedreceive = 183,
> + loongarch_sys_mq_notify = 184,
> + loongarch_sys_mq_getsetattr = 185,
> + loongarch_sys_msgget = 186,
> + loongarch_sys_msgctl = 187,
> + loongarch_sys_msgrcv = 188,
> + loongarch_sys_msgsnd = 189,
> + loongarch_sys_semget = 190,
> + loongarch_sys_semctl = 191,
> + loongarch_sys_semtimedop = 192,
> + loongarch_sys_semop = 193,
> + loongarch_sys_shmget = 194,
> + loongarch_sys_shmctl = 195,
> + loongarch_sys_shmat = 196,
> + loongarch_sys_shmdt = 197,
> + loongarch_sys_socket = 198,
> + loongarch_sys_socketpair = 199,
> + loongarch_sys_bind = 200,
> + loongarch_sys_listen = 201,
> + loongarch_sys_accept = 202,
> + loongarch_sys_connect = 203,
> + loongarch_sys_getsockname = 204,
> + loongarch_sys_getpeername = 205,
> + loongarch_sys_sendto = 206,
> + loongarch_sys_recvfrom = 207,
> + loongarch_sys_setsockopt = 208,
> + loongarch_sys_getsockopt = 209,
> + loongarch_sys_shutdown = 210,
> + loongarch_sys_sendmsg = 211,
> + loongarch_sys_recvmsg = 212,
> + loongarch_sys_readahead = 213,
> + loongarch_sys_brk = 214,
> + loongarch_sys_munmap = 215,
> + loongarch_sys_mremap = 216,
> + loongarch_sys_add_key = 217,
> + loongarch_sys_request_key = 218,
> + loongarch_sys_keyctl = 219,
> + loongarch_sys_clone = 220,
> + loongarch_sys_execve = 221,
> + loongarch_sys_mmap = 222,
> + loongarch_sys_fadvise64 = 223,
> + loongarch_sys_swapon = 224,
> + loongarch_sys_swapoff = 225,
> + loongarch_sys_mprotect = 226,
> + loongarch_sys_msync = 227,
> + loongarch_sys_mlock = 228,
> + loongarch_sys_munlock = 229,
> + loongarch_sys_mlockall = 230,
> + loongarch_sys_munlockall = 231,
> + loongarch_sys_mincore = 232,
> + loongarch_sys_madvise = 233,
> + loongarch_sys_remap_file_pages = 234,
> + loongarch_sys_mbind = 235,
> + loongarch_sys_get_mempolicy = 236,
> + loongarch_sys_set_mempolicy = 237,
> + loongarch_sys_migrate_pages = 238,
> + loongarch_sys_move_pages = 239,
> + loongarch_sys_rt_tgsigqueueinfo = 240,
> + loongarch_sys_perf_event_open = 241,
> + loongarch_sys_accept4 = 242,
> + loongarch_sys_recvmmsg = 243,
> + loongarch_sys_wait4 = 260,
> + loongarch_sys_prlimit64 = 261,
> + loongarch_sys_fanotify_init = 262,
> + loongarch_sys_fanotify_mark = 263,
> + loongarch_sys_name_to_handle_at = 264,
> + loongarch_sys_open_by_handle_at = 265,
> + loongarch_sys_clock_adjtime = 266,
> + loongarch_sys_syncfs = 267,
> + loongarch_sys_setns = 268,
> + loongarch_sys_sendmmsg = 269,
> + loongarch_sys_process_vm_readv = 270,
> + loongarch_sys_process_vm_writev = 271,
> + loongarch_sys_kcmp = 272,
> + loongarch_sys_finit_module = 273,
> + loongarch_sys_sched_setattr = 274,
> + loongarch_sys_sched_getattr = 275,
> + loongarch_sys_renameat2 = 276,
> + loongarch_sys_seccomp = 277,
> + loongarch_sys_getrandom = 278,
> + loongarch_sys_memfd_create = 279,
> + loongarch_sys_bpf = 280,
> + loongarch_sys_execveat = 281,
> + loongarch_sys_userfaultfd = 282,
> + loongarch_sys_membarrier = 283,
> + loongarch_sys_mlock2 = 284,
> + loongarch_sys_copy_file_range = 285,
> + loongarch_sys_preadv2 = 286,
> + loongarch_sys_pwritev2 = 287,
> + loongarch_sys_pkey_mprotect = 288,
> + loongarch_sys_pkey_alloc = 289,
> + loongarch_sys_pkey_free = 290,
> + loongarch_sys_statx = 291,
> + loongarch_sys_io_pgetevents = 292,
> + loongarch_sys_rseq = 293,
> + loongarch_sys_kexec_file_load = 294,
> +
> + loongarch_sys_pidfd_send_signal = 424,
> + loongarch_sys_io_uring_setup = 425,
> + loongarch_sys_io_uring_enter = 426,
> + loongarch_sys_io_uring_register = 427,
> + loongarch_sys_open_tree = 428,
> + loongarch_sys_move_mount = 429,
> + loongarch_sys_fsopen = 430,
> + loongarch_sys_fsconfig = 431,
> + loongarch_sys_fsmount = 432,
> + loongarch_sys_fspick = 433,
> + loongarch_sys_pidfd_open = 434,
> + loongarch_sys_clone3 = 435,
> + loongarch_sys_close_range = 436,
> + loongarch_sys_openat2 = 437,
> + loongarch_sys_pidfd_getfd = 438,
> + loongarch_sys_faccessat2 = 439,
> + loongarch_sys_process_madvise = 440,
> + loongarch_sys_epoll_pwait2 = 441,
> + loongarch_sys_mount_setattr = 442,
> + loongarch_sys_quotactl_fd = 443,
> + loongarch_sys_landlock_create_ruleset = 444,
> + loongarch_sys_landlock_add_rule = 445,
> + loongarch_sys_landlock_restrict_self = 446,
> +
> + loongarch_sys_process_mrelease = 448,
> + loongarch_sys_futex_waitv = 449,
> + loongarch_sys_set_mempolicy_home_node = 450,
> + loongarch_sys_cachestat = 451,
> + loongarch_sys_fchmodat2 = 452,
> + loongarch_sys_map_shadow_stack = 453,
> + loongarch_sys_futex_wake = 454,
> + loongarch_sys_futex_wait = 455,
> + loongarch_sys_futex_requeue = 456,
> + loongarch_sys_statmount = 457,
> + loongarch_sys_listmount = 458,
> + loongarch_sys_lsm_get_self_attr = 459,
> + loongarch_sys_lsm_set_self_attr = 460,
> + loongarch_sys_lsm_list_modules = 461,
> + loongarch_sys_mseal = 462,
> + loongarch_sys_syscalls = 463,
> +};
> +
> +#endif /* ARCH_LOONGARCH_INSN_H */
> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
> index 86e7ed8a0bc..a027edd07e5 100644
> --- a/gdb/loongarch-linux-tdep.c
> +++ b/gdb/loongarch-linux-tdep.c
> @@ -18,15 +18,21 @@
> You should have received a copy of the GNU General Public License
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> +#include "arch/loongarch-syscall.h"
> #include "extract-store-integer.h"
> +#include "gdbarch.h"
> #include "glibc-tdep.h"
> #include "inferior.h"
> +#include "linux-record.h"
> #include "linux-tdep.h"
> #include "loongarch-tdep.h"
> +#include "record-full.h"
> +#include "regset.h"
> #include "solib-svr4.h"
> #include "target-descriptions.h"
> #include "trad-frame.h"
> #include "tramp-frame.h"
> +#include "value.h"
> #include "xml-syscall.h"
>
> /* The syscall's XML filename for LoongArch. */
> @@ -566,6 +572,561 @@ loongarch_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread
> return ret;
> }
>
> +static linux_record_tdep loongarch_linux_record_tdep;
> +
> +/* loongarch_canonicalize_syscall maps syscall ids from the native LoongArch
> + linux set of syscall ids into a canonical set of syscall ids used by
> + process record. */
> +
> +static enum gdb_syscall
> +loongarch_canonicalize_syscall (enum loongarch_syscall syscall_number)
> +{
> +#define SYSCALL_MAP(SYSCALL) case loongarch_sys_##SYSCALL: \
> + return gdb_sys_##SYSCALL
> +
> +#define UNSUPPORTED_SYSCALL_MAP(SYSCALL) case loongarch_sys_##SYSCALL: \
> + return gdb_sys_no_syscall
> +
> + switch(syscall_number)
> + {
> + SYSCALL_MAP (io_setup);
> + SYSCALL_MAP (io_destroy);
> + SYSCALL_MAP (io_submit);
> + SYSCALL_MAP (io_cancel);
> + SYSCALL_MAP (io_getevents);
> + SYSCALL_MAP (setxattr);
> + SYSCALL_MAP (lsetxattr);
> + SYSCALL_MAP (fsetxattr);
> + SYSCALL_MAP (getxattr);
> + SYSCALL_MAP (lgetxattr);
> + SYSCALL_MAP (fgetxattr);
> + SYSCALL_MAP (listxattr);
> + SYSCALL_MAP (llistxattr);
> + SYSCALL_MAP (flistxattr);
> + SYSCALL_MAP (removexattr);
> + SYSCALL_MAP (lremovexattr);
> + SYSCALL_MAP (fremovexattr);
> + SYSCALL_MAP (getcwd);
> + SYSCALL_MAP (lookup_dcookie);
> + SYSCALL_MAP (eventfd2);
> + SYSCALL_MAP (epoll_create1);
> + SYSCALL_MAP (epoll_ctl);
> + SYSCALL_MAP (epoll_pwait);
> + SYSCALL_MAP (dup);
> + SYSCALL_MAP (dup3);
> + SYSCALL_MAP (fcntl);
> + SYSCALL_MAP (inotify_init1);
> + SYSCALL_MAP (inotify_add_watch);
> + SYSCALL_MAP (inotify_rm_watch);
> + SYSCALL_MAP (ioctl);
> + SYSCALL_MAP (ioprio_set);
> + SYSCALL_MAP (ioprio_get);
> + SYSCALL_MAP (flock);
> + SYSCALL_MAP (mknodat);
> + SYSCALL_MAP (mkdirat);
> + SYSCALL_MAP (unlinkat);
> + SYSCALL_MAP (symlinkat);
> + SYSCALL_MAP (linkat);
> + UNSUPPORTED_SYSCALL_MAP (umount2);
> + SYSCALL_MAP (mount);
> + SYSCALL_MAP (pivot_root);
> + SYSCALL_MAP (nfsservctl);
> + SYSCALL_MAP (statfs);
> + SYSCALL_MAP (truncate);
> + SYSCALL_MAP (ftruncate);
> + SYSCALL_MAP (fallocate);
> + SYSCALL_MAP (faccessat);
> + SYSCALL_MAP (fchdir);
> + SYSCALL_MAP (chroot);
> + SYSCALL_MAP (fchmod);
> + SYSCALL_MAP (fchmodat);
> + SYSCALL_MAP (fchownat);
> + SYSCALL_MAP (fchown);
> + SYSCALL_MAP (openat);
> + SYSCALL_MAP (close);
> + SYSCALL_MAP (vhangup);
> + SYSCALL_MAP (pipe2);
> + SYSCALL_MAP (quotactl);
> + SYSCALL_MAP (getdents64);
> + SYSCALL_MAP (lseek);
> + SYSCALL_MAP (read);
> + SYSCALL_MAP (write);
> + SYSCALL_MAP (readv);
> + SYSCALL_MAP (writev);
> + SYSCALL_MAP (pread64);
> + SYSCALL_MAP (pwrite64);
> + UNSUPPORTED_SYSCALL_MAP (preadv);
> + UNSUPPORTED_SYSCALL_MAP (pwritev);
> + SYSCALL_MAP (sendfile);
> + SYSCALL_MAP (pselect6);
> + SYSCALL_MAP (ppoll);
> + UNSUPPORTED_SYSCALL_MAP (signalfd4);
> + SYSCALL_MAP (vmsplice);
> + SYSCALL_MAP (splice);
> + SYSCALL_MAP (tee);
> + SYSCALL_MAP (readlinkat);
> + SYSCALL_MAP (newfstatat);
> + SYSCALL_MAP (fstat);
> + SYSCALL_MAP (sync);
> + SYSCALL_MAP (fsync);
> + SYSCALL_MAP (fdatasync);
> + SYSCALL_MAP (sync_file_range);
> + UNSUPPORTED_SYSCALL_MAP (timerfd_create);
> + UNSUPPORTED_SYSCALL_MAP (timerfd_settime);
> + UNSUPPORTED_SYSCALL_MAP (timerfd_gettime);
> + UNSUPPORTED_SYSCALL_MAP (utimensat);
> + SYSCALL_MAP (acct);
> + SYSCALL_MAP (capget);
> + SYSCALL_MAP (capset);
> + SYSCALL_MAP (personality);
> + SYSCALL_MAP (exit);
> + SYSCALL_MAP (exit_group);
> + SYSCALL_MAP (waitid);
> + SYSCALL_MAP (set_tid_address);
> + SYSCALL_MAP (unshare);
> + SYSCALL_MAP (futex);
> + SYSCALL_MAP (set_robust_list);
> + SYSCALL_MAP (get_robust_list);
> + SYSCALL_MAP (nanosleep);
> + SYSCALL_MAP (getitimer);
> + SYSCALL_MAP (setitimer);
> + SYSCALL_MAP (kexec_load);
> + SYSCALL_MAP (init_module);
> + SYSCALL_MAP (delete_module);
> + SYSCALL_MAP (timer_create);
> + SYSCALL_MAP (timer_settime);
> + SYSCALL_MAP (timer_gettime);
> + SYSCALL_MAP (timer_getoverrun);
> + SYSCALL_MAP (timer_delete);
> + SYSCALL_MAP (clock_settime);
> + SYSCALL_MAP (clock_gettime);
> + SYSCALL_MAP (clock_getres);
> + SYSCALL_MAP (clock_nanosleep);
> + SYSCALL_MAP (syslog);
> + SYSCALL_MAP (ptrace);
> + SYSCALL_MAP (sched_setparam);
> + SYSCALL_MAP (sched_setscheduler);
> + SYSCALL_MAP (sched_getscheduler);
> + SYSCALL_MAP (sched_getparam);
> + SYSCALL_MAP (sched_setaffinity);
> + SYSCALL_MAP (sched_getaffinity);
> + SYSCALL_MAP (sched_yield);
> + SYSCALL_MAP (sched_get_priority_max);
> + SYSCALL_MAP (sched_get_priority_min);
> + SYSCALL_MAP (sched_rr_get_interval);
> + SYSCALL_MAP (kill);
> + SYSCALL_MAP (tkill);
> + SYSCALL_MAP (tgkill);
> + SYSCALL_MAP (sigaltstack);
> + SYSCALL_MAP (rt_sigsuspend);
> + SYSCALL_MAP (rt_sigaction);
> + SYSCALL_MAP (rt_sigprocmask);
> + SYSCALL_MAP (rt_sigpending);
> + SYSCALL_MAP (rt_sigtimedwait);
> + SYSCALL_MAP (rt_sigqueueinfo);
> + SYSCALL_MAP (rt_sigreturn);
> + SYSCALL_MAP (setpriority);
> + SYSCALL_MAP (getpriority);
> + SYSCALL_MAP (reboot);
> + SYSCALL_MAP (setregid);
> + SYSCALL_MAP (setgid);
> + SYSCALL_MAP (setreuid);
> + SYSCALL_MAP (setuid);
> + SYSCALL_MAP (setresuid);
> + SYSCALL_MAP (getresuid);
> + SYSCALL_MAP (setresgid);
> + SYSCALL_MAP (getresgid);
> + SYSCALL_MAP (setfsuid);
> + SYSCALL_MAP (setfsgid);
> + SYSCALL_MAP (times);
> + SYSCALL_MAP (setpgid);
> + SYSCALL_MAP (getpgid);
> + SYSCALL_MAP (getsid);
> + SYSCALL_MAP (setsid);
> + SYSCALL_MAP (getgroups);
> + SYSCALL_MAP (setgroups);
> + SYSCALL_MAP (uname);
> + SYSCALL_MAP (sethostname);
> + SYSCALL_MAP (setdomainname);
> + SYSCALL_MAP (getrusage);
> + SYSCALL_MAP (umask);
> + SYSCALL_MAP (prctl);
> + SYSCALL_MAP (getcpu);
> + SYSCALL_MAP (gettimeofday);
> + SYSCALL_MAP (settimeofday);
> + SYSCALL_MAP (adjtimex);
> + SYSCALL_MAP (getpid);
> + SYSCALL_MAP (getppid);
> + SYSCALL_MAP (getuid);
> + SYSCALL_MAP (geteuid);
> + SYSCALL_MAP (getgid);
> + SYSCALL_MAP (getegid);
> + SYSCALL_MAP (gettid);
> + SYSCALL_MAP (sysinfo);
> + SYSCALL_MAP (mq_open);
> + SYSCALL_MAP (mq_unlink);
> + SYSCALL_MAP (mq_timedsend);
> + SYSCALL_MAP (mq_timedreceive);
> + SYSCALL_MAP (mq_notify);
> + SYSCALL_MAP (mq_getsetattr);
> + SYSCALL_MAP (msgget);
> + SYSCALL_MAP (msgctl);
> + SYSCALL_MAP (msgrcv);
> + SYSCALL_MAP (msgsnd);
> + SYSCALL_MAP (semget);
> + SYSCALL_MAP (semctl);
> + SYSCALL_MAP (semtimedop);
> + SYSCALL_MAP (semop);
> + SYSCALL_MAP (shmget);
> + SYSCALL_MAP (shmctl);
> + SYSCALL_MAP (shmat);
> + SYSCALL_MAP (shmdt);
> + SYSCALL_MAP (socket);
> + SYSCALL_MAP (socketpair);
> + SYSCALL_MAP (bind);
> + SYSCALL_MAP (listen);
> + SYSCALL_MAP (accept);
> + SYSCALL_MAP (connect);
> + SYSCALL_MAP (getsockname);
> + SYSCALL_MAP (getpeername);
> + SYSCALL_MAP (sendto);
> + SYSCALL_MAP (recvfrom);
> + SYSCALL_MAP (setsockopt);
> + SYSCALL_MAP (getsockopt);
> + SYSCALL_MAP (shutdown);
> + SYSCALL_MAP (sendmsg);
> + SYSCALL_MAP (recvmsg);
> + SYSCALL_MAP (readahead);
> + SYSCALL_MAP (brk);
> + SYSCALL_MAP (munmap);
> + SYSCALL_MAP (mremap);
> + SYSCALL_MAP (add_key);
> + SYSCALL_MAP (request_key);
> + SYSCALL_MAP (keyctl);
> + SYSCALL_MAP (clone);
> + SYSCALL_MAP (execve);
> +
> + case loongarch_sys_mmap:
> + return gdb_sys_mmap2;
> +
> + SYSCALL_MAP (fadvise64);
> + SYSCALL_MAP (swapon);
> + SYSCALL_MAP (swapoff);
> + SYSCALL_MAP (mprotect);
> + SYSCALL_MAP (msync);
> + SYSCALL_MAP (mlock);
> + SYSCALL_MAP (munlock);
> + SYSCALL_MAP (mlockall);
> + SYSCALL_MAP (munlockall);
> + SYSCALL_MAP (mincore);
> + SYSCALL_MAP (madvise);
> + SYSCALL_MAP (remap_file_pages);
> + SYSCALL_MAP (mbind);
> + SYSCALL_MAP (get_mempolicy);
> + SYSCALL_MAP (set_mempolicy);
> + SYSCALL_MAP (migrate_pages);
> + SYSCALL_MAP (move_pages);
> + UNSUPPORTED_SYSCALL_MAP (rt_tgsigqueueinfo);
> + UNSUPPORTED_SYSCALL_MAP (perf_event_open);
> + UNSUPPORTED_SYSCALL_MAP (accept4);
> + UNSUPPORTED_SYSCALL_MAP (recvmmsg);
> + SYSCALL_MAP (wait4);
> + UNSUPPORTED_SYSCALL_MAP (prlimit64);
> + UNSUPPORTED_SYSCALL_MAP (fanotify_init);
> + UNSUPPORTED_SYSCALL_MAP (fanotify_mark);
> + UNSUPPORTED_SYSCALL_MAP (name_to_handle_at);
> + UNSUPPORTED_SYSCALL_MAP (open_by_handle_at);
> + UNSUPPORTED_SYSCALL_MAP (clock_adjtime);
> + UNSUPPORTED_SYSCALL_MAP (syncfs);
> + UNSUPPORTED_SYSCALL_MAP (setns);
> + UNSUPPORTED_SYSCALL_MAP (sendmmsg);
> + UNSUPPORTED_SYSCALL_MAP (process_vm_readv);
> + UNSUPPORTED_SYSCALL_MAP (process_vm_writev);
> + UNSUPPORTED_SYSCALL_MAP (kcmp);
> + UNSUPPORTED_SYSCALL_MAP (finit_module);
> + UNSUPPORTED_SYSCALL_MAP (sched_setattr);
> + UNSUPPORTED_SYSCALL_MAP (sched_getattr);
> + UNSUPPORTED_SYSCALL_MAP (renameat2);
> + UNSUPPORTED_SYSCALL_MAP (seccomp);
> + SYSCALL_MAP (getrandom);
> + UNSUPPORTED_SYSCALL_MAP (memfd_create);
> + UNSUPPORTED_SYSCALL_MAP (bpf);
> + UNSUPPORTED_SYSCALL_MAP (execveat);
> + UNSUPPORTED_SYSCALL_MAP (userfaultfd);
> + UNSUPPORTED_SYSCALL_MAP (membarrier);
> + UNSUPPORTED_SYSCALL_MAP (mlock2);
> + UNSUPPORTED_SYSCALL_MAP (copy_file_range);
> + UNSUPPORTED_SYSCALL_MAP (preadv2);
> + UNSUPPORTED_SYSCALL_MAP (pwritev2);
> + UNSUPPORTED_SYSCALL_MAP (pkey_mprotect);
> + UNSUPPORTED_SYSCALL_MAP (pkey_alloc);
> + UNSUPPORTED_SYSCALL_MAP (pkey_free);
> + SYSCALL_MAP (statx);
> + UNSUPPORTED_SYSCALL_MAP (io_pgetevents);
> + UNSUPPORTED_SYSCALL_MAP (rseq);
> + UNSUPPORTED_SYSCALL_MAP (kexec_file_load);
> + UNSUPPORTED_SYSCALL_MAP (pidfd_send_signal);
> + UNSUPPORTED_SYSCALL_MAP (io_uring_setup);
> + UNSUPPORTED_SYSCALL_MAP (io_uring_enter);
> + UNSUPPORTED_SYSCALL_MAP (io_uring_register);
> + UNSUPPORTED_SYSCALL_MAP (open_tree);
> + UNSUPPORTED_SYSCALL_MAP (move_mount);
> + UNSUPPORTED_SYSCALL_MAP (fsopen);
> + UNSUPPORTED_SYSCALL_MAP (fsconfig);
> + UNSUPPORTED_SYSCALL_MAP (fsmount);
> + UNSUPPORTED_SYSCALL_MAP (fspick);
> + UNSUPPORTED_SYSCALL_MAP (pidfd_open);
> + UNSUPPORTED_SYSCALL_MAP (clone3);
> + UNSUPPORTED_SYSCALL_MAP (close_range);
> + UNSUPPORTED_SYSCALL_MAP (openat2);
> + UNSUPPORTED_SYSCALL_MAP (pidfd_getfd);
> + UNSUPPORTED_SYSCALL_MAP (faccessat2);
> + UNSUPPORTED_SYSCALL_MAP (process_madvise);
> + UNSUPPORTED_SYSCALL_MAP (epoll_pwait2);
> + UNSUPPORTED_SYSCALL_MAP (mount_setattr);
> + UNSUPPORTED_SYSCALL_MAP (quotactl_fd);
> + UNSUPPORTED_SYSCALL_MAP (landlock_create_ruleset);
> + UNSUPPORTED_SYSCALL_MAP (landlock_add_rule);
> + UNSUPPORTED_SYSCALL_MAP (landlock_restrict_self);
> + UNSUPPORTED_SYSCALL_MAP (process_mrelease);
> + UNSUPPORTED_SYSCALL_MAP (futex_waitv);
> + UNSUPPORTED_SYSCALL_MAP (set_mempolicy_home_node);
> + UNSUPPORTED_SYSCALL_MAP (cachestat);
> + UNSUPPORTED_SYSCALL_MAP (fchmodat2);
> + UNSUPPORTED_SYSCALL_MAP (map_shadow_stack);
> + UNSUPPORTED_SYSCALL_MAP (futex_wake);
> + UNSUPPORTED_SYSCALL_MAP (futex_wait);
> + UNSUPPORTED_SYSCALL_MAP (futex_requeue);
> + UNSUPPORTED_SYSCALL_MAP (statmount);
> + UNSUPPORTED_SYSCALL_MAP (listmount);
> + UNSUPPORTED_SYSCALL_MAP (lsm_get_self_attr);
> + UNSUPPORTED_SYSCALL_MAP (lsm_set_self_attr);
> + UNSUPPORTED_SYSCALL_MAP (lsm_list_modules);
> + UNSUPPORTED_SYSCALL_MAP (mseal);
> + UNSUPPORTED_SYSCALL_MAP (syscalls);
> + default:
> + return gdb_sys_no_syscall;
> + }
Small nit, but after this function, it would be nice if SYSCALL_MAP and
UNSUPPORTED_SYSCALL_MAP were undefined so they aren't accidentally exported.
> +}
> +
> +static int
> +loongarch_record_all_but_pc_registers (struct regcache *regcache)
> +{
> +
> + /* Record General purpose Registers. */
> + for (int i = 0; i < 32; ++i)
> + if (record_full_arch_list_add_reg (regcache, i))
> + return -1;
> +
> + /* Record orig_a0 */
> + if (record_full_arch_list_add_reg (regcache, LOONGARCH_ORIG_A0_REGNUM))
> + return -1;
> +
> + /* Record badvaddr */
> + if (record_full_arch_list_add_reg (regcache, LOONGARCH_BADV_REGNUM))
> + return -1;
> +
> + return 0;
> +}
> +
> +/* Handler for LoongArch architechture system call instruction recording. */
> +
> +static int
> +loongarch_linux_syscall_record (struct regcache *regcache,
> + unsigned long syscall_number)
> +{
> + int ret = 0;
> + enum gdb_syscall syscall_gdb;
> +
> + syscall_gdb =
> + loongarch_canonicalize_syscall ((enum loongarch_syscall) syscall_number);
> +
> + if (syscall_gdb < 0)
> + {
> + gdb_printf (gdb_stderr,
> + _("Process record and replay target doesn't "
> + "support syscall number %s\n"),
> + plongest (syscall_number));
> + }
> +
> + if (syscall_gdb == gdb_sys_sigreturn || syscall_gdb == gdb_sys_rt_sigreturn)
> + return loongarch_record_all_but_pc_registers (regcache);
> +
> + ret = record_linux_system_call (syscall_gdb, regcache,
> + &loongarch_linux_record_tdep);
> +
> + if (ret != 0)
> + return ret;
> +
> + /* Record the return value of the system call. */
> + if (record_full_arch_list_add_reg (regcache, LOONGARCH_A0_REGNUM))
> + return -1;
> +
> + return 0;
> +}
> +
> +/* Initialize the loongarch_linux_record_tdep. These values are the size
> + of the type that will be used in a system call. They are obtained from
> + Linux Kernel source. */
> +
> +static void
> +Init_loongarch_linux_record_tdep (struct gdbarch *gdbarch)
Capital I here should be lower case.
--
Cheers,
Guinevere Larsen
She/Her/Hers
> +{
> + loongarch_linux_record_tdep.size_pointer
> + = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
> + loongarch_linux_record_tdep.size_tms = 32;
> + loongarch_linux_record_tdep.size_loff_t = 8;
> + loongarch_linux_record_tdep.size_flock = 32;
> + loongarch_linux_record_tdep.size_oldold_utsname = 45;
> + loongarch_linux_record_tdep.size_ustat = 32;
> + loongarch_linux_record_tdep.size_old_sigaction = 32;
> + loongarch_linux_record_tdep.size_old_sigset_t = 8;
> + loongarch_linux_record_tdep.size_rlimit = 16;
> + loongarch_linux_record_tdep.size_rusage = 144;
> + loongarch_linux_record_tdep.size_timeval = 16;
> + loongarch_linux_record_tdep.size_timezone = 8;
> + loongarch_linux_record_tdep.size_old_gid_t = 4;
> + loongarch_linux_record_tdep.size_old_uid_t = 4;
> + loongarch_linux_record_tdep.size_fd_set = 128;
> + loongarch_linux_record_tdep.size_old_dirent = 280;
> + loongarch_linux_record_tdep.size_statfs = 120;
> + loongarch_linux_record_tdep.size_statfs64 = 120;
> + loongarch_linux_record_tdep.size_sockaddr = 16;
> + loongarch_linux_record_tdep.size_int
> + = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT;
> + loongarch_linux_record_tdep.size_long
> + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
> + loongarch_linux_record_tdep.size_ulong
> + = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
> + loongarch_linux_record_tdep.size_msghdr = 56;
> + loongarch_linux_record_tdep.size_itimerval = 32;
> + loongarch_linux_record_tdep.size_stat = 144;
> + loongarch_linux_record_tdep.size_old_utsname = 325;
> + loongarch_linux_record_tdep.size_sysinfo = 112;
> + loongarch_linux_record_tdep.size_msqid_ds = 120;
> + loongarch_linux_record_tdep.size_shmid_ds = 112;
> + loongarch_linux_record_tdep.size_new_utsname = 390;
> + loongarch_linux_record_tdep.size_timex = 208;
> + loongarch_linux_record_tdep.size_mem_dqinfo = 72;
> + loongarch_linux_record_tdep.size_if_dqblk = 72;
> + loongarch_linux_record_tdep.size_fs_quota_stat = 80;
> + loongarch_linux_record_tdep.size_timespec = 16;
> + loongarch_linux_record_tdep.size_pollfd = 8;
> + loongarch_linux_record_tdep.size_NFS_FHSIZE = 32;
> + loongarch_linux_record_tdep.size_knfsd_fh = 132;
> + loongarch_linux_record_tdep.size_TASK_COMM_LEN = 16;
> + loongarch_linux_record_tdep.size_sigaction = 24;
> + loongarch_linux_record_tdep.size_sigset_t = 8;
> + loongarch_linux_record_tdep.size_siginfo_t = 128;
> + loongarch_linux_record_tdep.size_cap_user_data_t = 8;
> + loongarch_linux_record_tdep.size_stack_t = 24;
> + loongarch_linux_record_tdep.size_off_t = 8;
> + loongarch_linux_record_tdep.size_stat64 = 144;
> + loongarch_linux_record_tdep.size_gid_t = 4;
> + loongarch_linux_record_tdep.size_uid_t = 4;
> + loongarch_linux_record_tdep.size_PAGE_SIZE = 0x4000;
> + loongarch_linux_record_tdep.size_flock64 = 32;
> + loongarch_linux_record_tdep.size_user_desc = 16;
> + loongarch_linux_record_tdep.size_io_event = 32;
> + loongarch_linux_record_tdep.size_iocb = 64;
> + loongarch_linux_record_tdep.size_epoll_event = 12;
> + loongarch_linux_record_tdep.size_itimerspec = 32;
> + loongarch_linux_record_tdep.size_mq_attr = 64;
> + loongarch_linux_record_tdep.size_termios = 36;
> + loongarch_linux_record_tdep.size_termios2 = 44;
> + loongarch_linux_record_tdep.size_pid_t = 4;
> + loongarch_linux_record_tdep.size_winsize = 8;
> + loongarch_linux_record_tdep.size_serial_struct = 72;
> + loongarch_linux_record_tdep.size_serial_icounter_struct = 80;
> + loongarch_linux_record_tdep.size_hayes_esp_config = 12;
> + loongarch_linux_record_tdep.size_size_t = 8;
> + loongarch_linux_record_tdep.size_iovec = 16;
> + loongarch_linux_record_tdep.size_time_t = 8;
> +
> + /* These values are the second argument of system call "sys_ioctl".
> + They are obtained from Linux Kernel source. */
> + loongarch_linux_record_tdep.ioctl_TCGETS = 0x5401;
> + loongarch_linux_record_tdep.ioctl_TCSETS = 0x5402;
> + loongarch_linux_record_tdep.ioctl_TCSETSW = 0x5403;
> + loongarch_linux_record_tdep.ioctl_TCSETSF = 0x5404;
> + loongarch_linux_record_tdep.ioctl_TCGETA = 0x5405;
> + loongarch_linux_record_tdep.ioctl_TCSETA = 0x5406;
> + loongarch_linux_record_tdep.ioctl_TCSETAW = 0x5407;
> + loongarch_linux_record_tdep.ioctl_TCSETAF = 0x5408;
> + loongarch_linux_record_tdep.ioctl_TCSBRK = 0x5409;
> + loongarch_linux_record_tdep.ioctl_TCXONC = 0x540a;
> + loongarch_linux_record_tdep.ioctl_TCFLSH = 0x540b;
> + loongarch_linux_record_tdep.ioctl_TIOCEXCL = 0x540c;
> + loongarch_linux_record_tdep.ioctl_TIOCNXCL = 0x540d;
> + loongarch_linux_record_tdep.ioctl_TIOCSCTTY = 0x540e;
> + loongarch_linux_record_tdep.ioctl_TIOCGPGRP = 0x540f;
> + loongarch_linux_record_tdep.ioctl_TIOCSPGRP = 0x5410;
> + loongarch_linux_record_tdep.ioctl_TIOCOUTQ = 0x5411;
> + loongarch_linux_record_tdep.ioctl_TIOCSTI = 0x5412;
> + loongarch_linux_record_tdep.ioctl_TIOCGWINSZ = 0x5413;
> + loongarch_linux_record_tdep.ioctl_TIOCSWINSZ = 0x5414;
> + loongarch_linux_record_tdep.ioctl_TIOCMGET = 0x5415;
> + loongarch_linux_record_tdep.ioctl_TIOCMBIS = 0x5416;
> + loongarch_linux_record_tdep.ioctl_TIOCMBIC = 0x5417;
> + loongarch_linux_record_tdep.ioctl_TIOCMSET = 0x5418;
> + loongarch_linux_record_tdep.ioctl_TIOCGSOFTCAR = 0x5419;
> + loongarch_linux_record_tdep.ioctl_TIOCSSOFTCAR = 0x541a;
> + loongarch_linux_record_tdep.ioctl_FIONREAD = 0x541b;
> + loongarch_linux_record_tdep.ioctl_TIOCINQ = 0x541b;
> + loongarch_linux_record_tdep.ioctl_TIOCLINUX = 0x541c;
> + loongarch_linux_record_tdep.ioctl_TIOCCONS = 0x541d;
> + loongarch_linux_record_tdep.ioctl_TIOCGSERIAL = 0x541e;
> + loongarch_linux_record_tdep.ioctl_TIOCSSERIAL = 0x541f;
> + loongarch_linux_record_tdep.ioctl_TIOCPKT = 0x5420;
> + loongarch_linux_record_tdep.ioctl_FIONBIO = 0x5421;
> + loongarch_linux_record_tdep.ioctl_TIOCNOTTY = 0x5422;
> + loongarch_linux_record_tdep.ioctl_TIOCSETD = 0x5423;
> + loongarch_linux_record_tdep.ioctl_TIOCGETD = 0x5424;
> + loongarch_linux_record_tdep.ioctl_TCSBRKP = 0x5425;
> + loongarch_linux_record_tdep.ioctl_TIOCTTYGSTRUCT = 0x5426;
> + loongarch_linux_record_tdep.ioctl_TIOCSBRK = 0x5427;
> + loongarch_linux_record_tdep.ioctl_TIOCCBRK = 0x5428;
> + loongarch_linux_record_tdep.ioctl_TIOCGSID = 0x5429;
> + loongarch_linux_record_tdep.ioctl_TCGETS2 = 0x802c542a;
> + loongarch_linux_record_tdep.ioctl_TCSETS2 = 0x402c542b;
> + loongarch_linux_record_tdep.ioctl_TCSETSW2 = 0x402c542c;
> + loongarch_linux_record_tdep.ioctl_TCSETSF2 = 0x402c542d;
> + loongarch_linux_record_tdep.ioctl_TIOCGPTN = 0x80045430;
> + loongarch_linux_record_tdep.ioctl_TIOCSPTLCK = 0x40045431;
> + loongarch_linux_record_tdep.ioctl_FIONCLEX = 0x5450;
> + loongarch_linux_record_tdep.ioctl_FIOCLEX = 0x5451;
> + loongarch_linux_record_tdep.ioctl_FIOASYNC = 0x5452;
> + loongarch_linux_record_tdep.ioctl_TIOCSERCONFIG = 0x5453;
> + loongarch_linux_record_tdep.ioctl_TIOCSERGWILD = 0x5454;
> + loongarch_linux_record_tdep.ioctl_TIOCSERSWILD = 0x5455;
> + loongarch_linux_record_tdep.ioctl_TIOCGLCKTRMIOS = 0x5456;
> + loongarch_linux_record_tdep.ioctl_TIOCSLCKTRMIOS = 0x5457;
> + loongarch_linux_record_tdep.ioctl_TIOCSERGSTRUCT = 0x5458;
> + loongarch_linux_record_tdep.ioctl_TIOCSERGETLSR = 0x5459;
> + loongarch_linux_record_tdep.ioctl_TIOCSERGETMULTI = 0x545a;
> + loongarch_linux_record_tdep.ioctl_TIOCSERSETMULTI = 0x545b;
> + loongarch_linux_record_tdep.ioctl_TIOCMIWAIT = 0x545c;
> + loongarch_linux_record_tdep.ioctl_TIOCGICOUNT = 0x545d;
> + loongarch_linux_record_tdep.ioctl_TIOCGHAYESESP = 0x545e;
> + loongarch_linux_record_tdep.ioctl_TIOCSHAYESESP = 0x545f;
> + loongarch_linux_record_tdep.ioctl_FIOQSIZE = 0x5460;
> +
> + /* These values are the second argument of system call "sys_fcntl"
> + and "sys_fcntl64". They are obtained from Linux Kernel source. */
> + loongarch_linux_record_tdep.fcntl_F_GETLK = 5;
> + loongarch_linux_record_tdep.fcntl_F_GETLK64 = 12;
> + loongarch_linux_record_tdep.fcntl_F_SETLK64 = 13;
> + loongarch_linux_record_tdep.fcntl_F_SETLKW64 = 14;
> +
> + loongarch_linux_record_tdep.arg1 = LOONGARCH_A0_REGNUM + 0;
> + loongarch_linux_record_tdep.arg2 = LOONGARCH_A0_REGNUM + 1;
> + loongarch_linux_record_tdep.arg3 = LOONGARCH_A0_REGNUM + 2;
> + loongarch_linux_record_tdep.arg4 = LOONGARCH_A0_REGNUM + 3;
> + loongarch_linux_record_tdep.arg5 = LOONGARCH_A0_REGNUM + 4;
> + loongarch_linux_record_tdep.arg6 = LOONGARCH_A0_REGNUM + 5;
> + loongarch_linux_record_tdep.arg7 = LOONGARCH_A0_REGNUM + 6;
> +}
> +
> /* Initialize LoongArch Linux ABI info. */
>
> static void
> @@ -605,6 +1166,10 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Reversible debugging, process record. */
> set_gdbarch_process_record (gdbarch, loongarch_process_record);
> +
> + /* Syscall record. */
> + tdep->loongarch_syscall_record = loongarch_linux_syscall_record;
> + Init_loongarch_linux_record_tdep (gdbarch);
> }
>
> /* Initialize LoongArch Linux target support. */
> diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
> index cf72c48b573..b13e35c8e33 100644
> --- a/gdb/loongarch-tdep.c
> +++ b/gdb/loongarch-tdep.c
> @@ -2388,6 +2388,22 @@ loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
> return LOONGARCH_RECORD_SUCCESS;
> }
>
> +/* Record handler for syscall instructions. */
> +
> +static unsigned int
> +loongarch_syscall_insn_record (loongarch_insn_record *loongarch_insn_r)
> +{
> + uint64_t syscall_number;
> + struct loongarch_gdbarch_tdep *tdep
> + = gdbarch_tdep<loongarch_gdbarch_tdep> (loongarch_insn_r->gdbarch);
> +
> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, LOONGARCH_A7_REGNUM,
> + &syscall_number);
> +
> + return tdep->loongarch_syscall_record (loongarch_insn_r->regcache,
> + syscall_number);
> +}
> +
> /* Decode insns type and invoke its record handler. */
>
> static unsigned int
> @@ -2411,6 +2427,8 @@ loongarch_record_decode_insn_handler (loongarch_insn_record *loongarch_insn_r)
> return loongarch_record_cond_load_insn (loongarch_insn_r);
> else if (is_cond_store_insn (loongarch_insn_r->insn))
> return loongarch_record_cond_store_insn (loongarch_insn_r);
> + else if (is_syscall_insn (loongarch_insn_r->insn))
> + return loongarch_syscall_insn_record (loongarch_insn_r);
>
> return LOONGARCH_RECORD_UNSUPPORTED;
> }
> diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
> index a148363c795..62f7edc1c45 100644
> --- a/gdb/loongarch-tdep.h
> +++ b/gdb/loongarch-tdep.h
> @@ -40,6 +40,10 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
> /* Features about the abi that impact how the gdbarch is configured. */
> struct loongarch_gdbarch_features abi_features;
>
> + /* syscall record. */
> + int (*loongarch_syscall_record) (struct regcache *regcache,
> + unsigned long syscall_number) = nullptr;
> +
> /* Return the expected next PC if FRAME is stopped at a syscall instruction. */
> CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) = nullptr;
> };
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc
2024-11-13 9:53 ` [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc Hui Li
@ 2024-11-13 15:01 ` Eli Zaretskii
0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2024-11-13 15:01 UTC (permalink / raw)
To: Hui Li; +Cc: gdb-patches, yangtiezhu
> From: Hui Li <lihui@loongson.cn>
> Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
> Date: Wed, 13 Nov 2024 17:53:55 +0800
>
> At present, process record/replay and reverse debugging has been
> implemented on LoongArch. Update the NEWS and doc to record this
> new change.
>
> Signed-off-by: Hui Li <lihui@loongson.cn>
> ---
> gdb/NEWS | 3 +++
> gdb/doc/gdb.texinfo | 2 +-
> 2 files changed, 4 insertions(+), 1 deletion(-)
Thanks, this is okay.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support
2024-11-13 12:41 ` Guinevere Larsen
@ 2024-11-14 17:23 ` Guinevere Larsen
2024-11-19 13:20 ` Hui Li
1 sibling, 0 replies; 13+ messages in thread
From: Guinevere Larsen @ 2024-11-14 17:23 UTC (permalink / raw)
To: Hui Li, gdb-patches; +Cc: Tiezhu Yang
On 11/13/24 9:41 AM, Guinevere Larsen wrote:
> On 11/13/24 6:53 AM, Hui Li wrote:
>> GDB provides a special process record and replay target that can
>> record a log of the process execution, and replay it later with
>> both forward and reverse execution commands. This patch adds the
>> basic support of process record and replay on LoongArch, it allows
>> users to debug basic LoongArch instructions and provides reverse
>> debugging support.
>>
>> Here is a simple example on LoongArch:
>>
>> $ cat test.c
>> int a = 0;
>> int main()
>> {
>> a = 1;
>> a = 2;
>> return 0;
>> }
>> $ gdb test
>> ...
>> (gdb) start
>> ...
>> Temporary breakpoint 1, main () at test.c:4
>> 4 a = 1;
>> (gdb) record
>> (gdb) p a
>> $1 = 0
>> (gdb) n
>> 5 a = 2;
>> (gdb) n
>> 6 return 0;
>> (gdb) p a
>> $2 = 2
>> (gdb) rn
>> 5 a = 2;
>> (gdb) rn
>>
>> Reached end of recorded history; stopping.
>> Backward execution from here not possible.
>> main () at test.c:4
>> 4 a = 1;
>> (gdb) p a
>> $3 = 0
>> (gdb) record stop
>> Process record is stopped and all execution logs are deleted.
>> (gdb) c
>> Continuing.
>> [Inferior 1 (process 129178) exited normally]
>>
>> Signed-off-by: Hui Li <lihui@loongson.cn>
>
> Hi! Thanks for doing this! More architectures supporting reverse
> debugging is always welcome :)
>
> I do have some comments on the patch as it is right now.
>
>> ---
>> gdb/configure.tgt | 2 +-
>> gdb/loongarch-linux-tdep.c | 3 +
>> gdb/loongarch-tdep.c | 592 +++++++++++++++++++++++++++++++++++++
>> gdb/loongarch-tdep.h | 3 +
>> gdb/testsuite/lib/gdb.exp | 2 +
>> 5 files changed, 601 insertions(+), 1 deletion(-)
>>
>> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
>> index 62df71b13fa..2d78c1182fa 100644
>> --- a/gdb/configure.tgt
>> +++ b/gdb/configure.tgt
>> @@ -363,7 +363,7 @@ lm32-*-*)
>> loongarch*-*-linux*)
>> # Target: LoongArch running Linux
>> gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
>> - linux-tdep.o solib-svr4.o"
>> + linux-tdep.o solib-svr4.o linux-record.o"
>> ;;
>> m32c-*-*)
>> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
>> index 71578060303..86e7ed8a0bc 100644
>> --- a/gdb/loongarch-linux-tdep.c
>> +++ b/gdb/loongarch-linux-tdep.c
>> @@ -602,6 +602,9 @@ loongarch_linux_init_abi (struct gdbarch_info
>> info, struct gdbarch *gdbarch)
>> /* Get the syscall number from the arch's register. */
>> set_gdbarch_get_syscall_number (gdbarch,
>> loongarch_linux_get_syscall_number);
>> +
>> + /* Reversible debugging, process record. */
>> + set_gdbarch_process_record (gdbarch, loongarch_process_record);
>> }
>> /* Initialize LoongArch Linux target support. */
>> diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
>> index c50dd7f4b78..cf72c48b573 100644
>> --- a/gdb/loongarch-tdep.c
>> +++ b/gdb/loongarch-tdep.c
>> @@ -18,12 +18,16 @@
>> along with this program. If not, see
>> <http://www.gnu.org/licenses/>. */
>> #include "arch-utils.h"
>> +#include "arch/loongarch-insn.h"
>> #include "dwarf2/frame.h"
>> #include "elf-bfd.h"
>> #include "extract-store-integer.h"
>> #include "frame-unwind.h"
>> #include "gdbcore.h"
>> +#include "linux-record.h"
>> #include "loongarch-tdep.h"
>> +#include "record.h"
>> +#include "record-full.h"
>> #include "reggroups.h"
>> #include "target.h"
>> #include "target-descriptions.h"
>> @@ -1889,6 +1893,594 @@ loongarch_gdbarch_init (struct gdbarch_info
>> info, struct gdbarch_list *arches)
>> return gdbarch;
>> }
>> +/* LoongArch process record-replay related structures, defines
>> etc. */
>> +
>> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int reg_len = LENGTH; \
>> + if (reg_len) \
>> + { \
>> + REGS = XNEWVEC (uint32_t, reg_len); \
>> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int mem_len = LENGTH; \
>> + if (mem_len) \
>> + { \
>> + MEMS = XNEWVEC (struct loongarch_mem_r, mem_len); \
>> + memcpy(&MEMS->len, &RECORD_BUF[0], \
>> + sizeof(struct loongarch_mem_r) * LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +/* LoongArch record/replay structures and enumerations. */
>> +
>> +struct loongarch_mem_r
>> +{
>> + uint64_t len; /* Record length. */
>> + uint64_t addr; /* Memory address. */
>> +};
>> +
>> +enum loongarch_record_result
>> +{
>> + LOONGARCH_RECORD_SUCCESS,
>> + LOONGARCH_RECORD_UNSUPPORTED,
>> + LOONGARCH_RECORD_UNKNOWN
>> +};
>> +
>> +struct loongarch_insn_record
>> +{
>> + struct gdbarch *gdbarch;
>> + struct regcache *regcache;
>> + CORE_ADDR this_addr; /* Addr of insn to be
>> recorded. */
>> + uint32_t insn; /* Insn to be
>> recorded. */
>> + uint32_t mem_rec_count; /* Count of memory
>> records. */
>> + uint32_t reg_rec_count; /* Count of register
>> records. */
>> + uint32_t *regs; /* Registers to be
>> recorded. */
>> + struct loongarch_mem_r *loongarch_mems; /* Memory location to be
>> recorded. */
>> +};
>
> Record-full is already infamous for being quite slow, and a
> significant part of it is due to dynamic memory allocation and reading
> inferior state (memory or registers). Your strategy here is doubling
> up the number of both allocations and accesses to the inferior. The
> code would perform much better if you just did the calls to the
> record-full functions instead of building it here first.
>
> Did you run into any troubles with that traditional approach that led
> you to design this strategy?
Ah, an unrelated patch led me to arm-tdep, which uses basically the same
strategy, I see where this comes from.
I guess since this is already used in the code, I won't oppose this
going in, but I would still encourage calling the record_full functions
directly instead for performance concerns.
--
Cheers,
Guinevere Larsen
She/Her/Hers
>
>> +
>> +/* Record handler for data processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_data_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rd;
>> + uint32_t record_buf[1];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for read time instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_read_time_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rd, rj;
>> + uint32_t record_buf[2];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + record_buf[1] = rj;
>> + loongarch_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for jump instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_jump_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + if (is_jirl_insn (loongarch_insn_r->insn))
>> + {
>> + int rd;
>> + uint32_t record_buf[1];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs,
>> loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if(is_bl_insn (loongarch_insn_r->insn))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = LOONGARCH_RA_REGNUM;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs,
>> loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for float data processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_float_data_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int fd;
>> + uint32_t record_buf[1];
>> + fd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
>> + + LOONGARCH_FIRST_FP_REGNUM;
>> + record_buf[0] = fd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for fcsr processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_fcsr_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int fcsr;
>> + uint32_t record_buf[1];
>> + fcsr = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
>> + + LOONGARCH_FCSR_REGNUM;
>> + record_buf[0] = fcsr;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition flag register processing
>> instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_fcc_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int cd, imm3_4;
>> + uint32_t record_buf[1];
>> + cd = loongarch_decode_imm ("0:3", loongarch_insn_r->insn, 0);
>> + imm3_4 = loongarch_decode_imm ("3:2", loongarch_insn_r->insn, 0);
>> + if (imm3_4 != 0)
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +
>> + record_buf[0] = cd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for float instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_float_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + if (is_movgr2fcsr_insn (loongarch_insn_r->insn))
>> + return loongarch_record_fcsr_proc_insn (loongarch_insn_r);
>> + else if (is_mov2cf_insn (loongarch_insn_r->insn))
>> + return loongarch_record_fcc_proc_insn (loongarch_insn_r);
>> + else
>> + return loongarch_record_float_data_proc_insn (loongarch_insn_r);
>> +}
>> +
>> +/* Record handler for store instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_store_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + enum store_types
>> + {
>> + STB, STH, STW, STD, STXB, STXH, STXW, STXD, STPTRW, STPTRD,
>> + SCW, SCD, FSTS, FSTD, FSTXS, FSTXD, VST, XVST, NOT_STORE
>> + };
>> + int store_type;
>> + uint64_t record_buf_mem[2];
>> + store_type = is_stb_insn (loongarch_insn_r->insn) ? STB :
>> + is_sth_insn (loongarch_insn_r->insn) ? STH :
>> + is_stw_insn (loongarch_insn_r->insn) ? STW :
>> + is_std_insn (loongarch_insn_r->insn) ? STD :
>> + is_stxb_insn (loongarch_insn_r->insn) ? STXB :
>> + is_stxh_insn (loongarch_insn_r->insn) ? STXH :
>> + is_stxw_insn (loongarch_insn_r->insn) ? STXW :
>> + is_stxd_insn (loongarch_insn_r->insn) ? STXD :
>> + is_stptrw_insn (loongarch_insn_r->insn) ? STPTRW :
>> + is_stptrd_insn (loongarch_insn_r->insn) ? STPTRD :
>> + is_scw_insn (loongarch_insn_r->insn) ? SCW :
>> + is_scd_insn (loongarch_insn_r->insn) ? SCD :
>> + is_fsts_insn (loongarch_insn_r->insn) ? FSTS :
>> + is_fstd_insn (loongarch_insn_r->insn) ? FSTD :
>> + is_fstxs_insn (loongarch_insn_r->insn) ? FSTXS :
>> + is_fstxd_insn (loongarch_insn_r->insn) ? FSTXD :
>> + is_vst_insn (loongarch_insn_r->insn) ? VST :
>> + is_xvst_insn (loongarch_insn_r->insn) ? XVST :
>> + NOT_STORE;
>> +
>> + if (store_type == STB || store_type == STH || store_type == STW
>> + || store_type == STD || store_type == FSTS || store_type == FSTD
>> + || store_type == VST || store_type == XVST)
>> + {
>> + int rj_num;
>> + int data_size;
>> + int imm;
>> + uint64_t rj_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + imm = loongarch_decode_imm ("10:12", loongarch_insn_r->insn, 1);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache,
>> rj_num, &rj_val);
>> + address = rj_val + imm;
>> + switch (store_type)
>> + {
>> + case STB:
>> + data_size = 1;
>> + break;
>> + case STH:
>> + data_size = 2;
>> + break;
>> + case STW:
>> + case FSTS:
>> + data_size = 4;
>> + break;
>> + case STD:
>> + case FSTD:
>> + data_size = 8;
>> + break;
>> + case VST:
>> + data_size = 16;
>> + break;
>> + case XVST:
>> + data_size = 32;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if (store_type == STXB || store_type == STXH || store_type ==
>> STXW
>> + || store_type == STXD || store_type == FSTXS || store_type ==
>> FSTXD)
>> + {
>> + int data_size;
>> + int rj_num, rk_num;
>> + uint64_t rj_val,rk_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn,
>> 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache,
>> rj_num, &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache,
>> rk_num, &rk_val);
>> + address = rj_val + rk_val;
>> + switch (store_type)
>> + {
>> + case STXB:
>> + data_size = 1;
>> + break;
>> + case STXH:
>> + data_size = 2;
>> + break;
>> + case STXW:
>> + case FSTXS:
>> + data_size = 4;
>> + break;
>> + case STXD:
>> + case FSTXD:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if (store_type == STPTRW || store_type == STPTRD ||
>> store_type == SCW
>> + || store_type == SCD)
>> + {
>> + int data_size;
>> + int rj_num;
>> + int imm;
>> + uint64_t rj_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + imm = loongarch_decode_imm ("10:14<<2",
>> + loongarch_insn_r->insn, 1);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache,
>> rj_num, &rj_val);
>> + address = rj_val + imm;
>> + switch (store_type)
>> + {
>> + case STPTRW:
>> + case SCW:
>> + data_size = 4;
>> + break;
>> + case STPTRD:
>> + case SCD:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> +
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +}
>> +
>> +/* Record handler for atomic memory access instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_am_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + int rj_num, rd_num;
>> + int word_or_double;
>> + int data_size;
>> + uint64_t address;
>> + uint32_t record_buf[1];
>> + uint64_t record_buf_mem[2];
>> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + word_or_double = loongarch_decode_imm ("15:1",
>> + loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &address);
>> + data_size = word_or_double == 1 ? 8 : 4;
>> + record_buf[0] = rd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> loongarch_insn_r->mem_rec_count,
>> + record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition load instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_cond_load_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> + {
>> + int rd_num, rj_num, rk_num, fd_num;
>> + uint64_t rj_val, rk_val;
>> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + fd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num,
>> &rk_val);
>> +
>> + if ((is_ldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
>> + || (is_ldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = rd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + }
>> + else if ((is_fldgt_insn (loongarch_insn_r->insn) && (rj_val >
>> rk_val))
>> + || (is_fldle_insn (loongarch_insn_r->insn) && (rj_val <=
>> rk_val)))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = fd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition store instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_cond_store_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rj_num, rk_num;
>> + int data_size;
>> + uint64_t rj_val, rk_val;
>> + uint32_t length_opcode;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num,
>> &rk_val);
>> +
>> + if ((is_stgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
>> + || (is_stle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
>> + {
>> + uint64_t record_buf_mem[2];
>> + length_opcode = loongarch_insn_r->insn & 0x00018000;
>> + switch (length_opcode)
>> + {
>> + case 0x00000000:
>> + data_size = 1;
>> + break;
>> + case 0x00008000:
>> + data_size = 2;
>> + break;
>> + case 0x00010000:
>> + data_size = 4;
>> + break;
>> + case 0x00018000:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = rj_val;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + }
>> + else if ((is_fstgt_insn (loongarch_insn_r->insn) && (rj_val >
>> rk_val))
>> + || (is_fstle_insn (loongarch_insn_r->insn) && (rj_val <=
>> rk_val)))
>> + {
>> + uint64_t record_buf_mem[2];
>> + length_opcode = loongarch_insn_r->insn & 0x00008000;
>> + switch (length_opcode)
>> + {
>> + case 0x00000000:
>> + data_size = 4;
>> + break;
>> + case 0x00008000:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = rj_val;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count,record_buf_mem);
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for special instructions like privilege instructions,
>> + barrier instructions and cache related instructions etc. */
>> +
>> +static unsigned int
>> +loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Decode insns type and invoke its record handler. */
>> +
>> +static unsigned int
>> +loongarch_record_decode_insn_handler (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + if (is_data_process_insn (loongarch_insn_r->insn))
>> + return loongarch_record_data_proc_insn (loongarch_insn_r);
>> + else if (is_jump_insn (loongarch_insn_r->insn))
>> + return loongarch_record_jump_insn (loongarch_insn_r);
>> + else if (is_store_insn (loongarch_insn_r->insn))
>> + return loongarch_record_store_insn (loongarch_insn_r);
>> + else if (is_read_time_insn (loongarch_insn_r->insn))
>> + return loongarch_record_read_time_insn (loongarch_insn_r);
>> + else if (is_float_insn (loongarch_insn_r->insn))
>> + return loongarch_record_float_insn (loongarch_insn_r);
>> + else if (is_special_insn (loongarch_insn_r->insn))
>> + return loongarch_record_special_insn (loongarch_insn_r);
>> + else if (is_am_insn (loongarch_insn_r->insn))
>> + return loongarch_record_am_insn (loongarch_insn_r);
>> + else if (is_cond_load_insn (loongarch_insn_r->insn))
>> + return loongarch_record_cond_load_insn (loongarch_insn_r);
>> + else if (is_cond_store_insn (loongarch_insn_r->insn))
>> + return loongarch_record_cond_store_insn (loongarch_insn_r);
>> +
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +}
>> +
>> +/* Parse the current instruction and record the values of the
>> registers and
>> + memory that will be changed in current instruction to
>> record_arch_list
>> + return -1 if something is wrong. */
>> +
>> +int
>> +loongarch_process_record (struct gdbarch *gdbarch, struct regcache
>> *regcache,
>> + CORE_ADDR insn_addr)
>> +{
>> + int rec_num = 0;
>> + uint32_t ret = 0;
>> + loongarch_insn_record loongarch_record;
>> +
>> + /* reset the content of loongarch_record */
>> + memset (&loongarch_record, 0, sizeof (loongarch_insn_record));
>> +
>> + /* write the loongarch_record */
>> + loongarch_record.gdbarch = gdbarch;
>> + loongarch_record.regcache = regcache;
>> + loongarch_record.this_addr = insn_addr;
>> +
>> + /* Get the current instruction */
>> + loongarch_record.insn = (uint32_t) loongarch_fetch_instruction
>> (insn_addr);
>> + ret = loongarch_record_decode_insn_handler (&loongarch_record);
>> + if (ret == LOONGARCH_RECORD_UNSUPPORTED)
>> + {
>> + gdb_printf (gdb_stderr,
>> + _("Process record does not support instruction "
>> + "0x%0x at address %s.\n"),
>> + loongarch_record.insn,
>> + paddress (gdbarch, insn_addr));
> When dealing with unsupported instructions, at least in x86, we use
> error, rather than gdb_printf to stderr. Using errors also ensure that
> a partially recorded instruction (which isn't the case yet, but should
> be) will be fully released by the caller of this function.
>> + ret = -1;
>> + }
>> + if (ret == LOONGARCH_RECORD_SUCCESS)
>> + {
>> + /* Record registers. */
>> + record_full_arch_list_add_reg (loongarch_record.regcache,
>> + LOONGARCH_PC_REGNUM);
>> + if (loongarch_record.reg_rec_count)
>> + {
>> + for (rec_num = 0; rec_num < loongarch_record.reg_rec_count;
>> rec_num++)
>> + {
>> + if (record_full_arch_list_add_reg (loongarch_record.regcache,
>> + loongarch_record.regs[rec_num]))
>> + ret = -1;
>> + }
>> + }
>> +
>> + /* Record memories. */
>> + if (loongarch_record.mem_rec_count)
>> + {
>> + for (rec_num = 0; rec_num < loongarch_record.mem_rec_count;
>> rec_num++)
>> + {
>> + if (record_full_arch_list_add_mem
>> + ((CORE_ADDR)loongarch_record.loongarch_mems[rec_num].addr,
>> + loongarch_record.loongarch_mems[rec_num].len))
>> + ret = -1;
>> + }
>> + }
>> +
>> + if (record_full_arch_list_add_end ())
>> + ret = -1;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> void _initialize_loongarch_tdep ();
>> void
>> _initialize_loongarch_tdep ()
>> diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
>> index 5c8108182ad..a148363c795 100644
>> --- a/gdb/loongarch-tdep.h
>> +++ b/gdb/loongarch-tdep.h
>> @@ -44,4 +44,7 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
>> CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) =
>> nullptr;
>> };
>> +extern int loongarch_process_record (struct gdbarch *gdbarch,
>> + struct regcache *regcache, CORE_ADDR addr);
>> +
>> #endif /* LOONGARCH_TDEP_H */
>> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
>> index 410f99e3350..9b994a9f640 100644
>> --- a/gdb/testsuite/lib/gdb.exp
>> +++ b/gdb/testsuite/lib/gdb.exp
>> @@ -3698,6 +3698,7 @@ proc supports_process_record {} {
>> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
>> || [istarget "i\[34567\]86-*-linux*"]
>> || [istarget "aarch64*-*-linux*"]
>> + || [istarget "loongarch*-*-linux*"]
>> || [istarget "powerpc*-*-linux*"]
>> || [istarget "s390*-*-linux*"] } {
>> return 1
>> @@ -3717,6 +3718,7 @@ proc supports_reverse {} {
>> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
>> || [istarget "i\[34567\]86-*-linux*"]
>> || [istarget "aarch64*-*-linux*"]
>> + || [istarget "loongarch*-*-linux*"]
>> || [istarget "powerpc*-*-linux*"]
>> || [istarget "s390*-*-linux*"] } {
>> return 1
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record
2024-11-13 12:03 ` Guinevere Larsen
@ 2024-11-19 13:07 ` Hui Li
0 siblings, 0 replies; 13+ messages in thread
From: Hui Li @ 2024-11-19 13:07 UTC (permalink / raw)
To: Guinevere Larsen, gdb-patches; +Cc: Tiezhu Yang
On 2024/11/13 下午8:03, Guinevere Larsen wrote:
> On 11/13/24 6:53 AM, Hui Li wrote:
>> GDB provides a special process record function that can record a log
>> of the process execution. The core of this feature is need to record
>> the execution of all instructions. This patch adds opcode definitions
>> and judgments in gdb/arch/loongarch-insn.h. This is preparation for
>> later patch on LoongArch, there is no effect for the other archs with
>> this patch.
>>
>> The LoongArch opcode and mask definitions are obtained from
>> https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=opcodes/loongarch-opc.c
>>
>> LoongArch instruction description refer to the LoongArch Reference
>> Manual:
>> https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
>>
>> Signed-off-by: Hui Li <lihui@loongson.cn>
>> ---
> I'm not familiar with loongarch, so I can't really review this specific
> patch in depth, but I have a bit of personal preference below.
>> gdb/arch/loongarch-insn.h | 1361 +++++++++++++++++++++++++++++++++++++
>> 1 file changed, 1361 insertions(+)
>> create mode 100644 gdb/arch/loongarch-insn.h
>>
> <snip>
>> +
>> +#define is_insn(insval,mask,funccode) (((insval) & (mask)) == funccode)
>
> I personally would prefer if this was defined as a tiny inline function,
> like riscv-tdep.c does it. I tend to find them easier to debug. I would
> extend this to the is_<type>_insn macros below as well. But I don't
> expect to work on loongarch (or even have loongarch hardware) any time
> soon, so feel free to ignore my preferences.
>
> If kept as a macro, funccode should probably be in parenthesis as well.
>
Thanks for your reply.
I will rewrite these code using inline function.
Thanks,
Hui
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support
2024-11-13 12:41 ` Guinevere Larsen
2024-11-14 17:23 ` Guinevere Larsen
@ 2024-11-19 13:20 ` Hui Li
1 sibling, 0 replies; 13+ messages in thread
From: Hui Li @ 2024-11-19 13:20 UTC (permalink / raw)
To: Guinevere Larsen, gdb-patches; +Cc: Tiezhu Yang
On 2024/11/13 下午8:41, Guinevere Larsen wrote:
> On 11/13/24 6:53 AM, Hui Li wrote:
>> GDB provides a special process record and replay target that can
>> record a log of the process execution, and replay it later with
>> both forward and reverse execution commands. This patch adds the
>> basic support of process record and replay on LoongArch, it allows
>> users to debug basic LoongArch instructions and provides reverse
>> debugging support.
>>
>> Here is a simple example on LoongArch:
>>
>> $ cat test.c
>> int a = 0;
>> int main()
>> {
>> a = 1;
>> a = 2;
>> return 0;
>> }
>> $ gdb test
>> ...
>> (gdb) start
>> ...
>> Temporary breakpoint 1, main () at test.c:4
>> 4 a = 1;
>> (gdb) record
>> (gdb) p a
>> $1 = 0
>> (gdb) n
>> 5 a = 2;
>> (gdb) n
>> 6 return 0;
>> (gdb) p a
>> $2 = 2
>> (gdb) rn
>> 5 a = 2;
>> (gdb) rn
>>
>> Reached end of recorded history; stopping.
>> Backward execution from here not possible.
>> main () at test.c:4
>> 4 a = 1;
>> (gdb) p a
>> $3 = 0
>> (gdb) record stop
>> Process record is stopped and all execution logs are deleted.
>> (gdb) c
>> Continuing.
>> [Inferior 1 (process 129178) exited normally]
>>
>> Signed-off-by: Hui Li <lihui@loongson.cn>
>
> Hi! Thanks for doing this! More architectures supporting reverse
> debugging is always welcome :)
>
> I do have some comments on the patch as it is right now.
>
>> ---
>> gdb/configure.tgt | 2 +-
>> gdb/loongarch-linux-tdep.c | 3 +
>> gdb/loongarch-tdep.c | 592 +++++++++++++++++++++++++++++++++++++
>> gdb/loongarch-tdep.h | 3 +
>> gdb/testsuite/lib/gdb.exp | 2 +
>> 5 files changed, 601 insertions(+), 1 deletion(-)
>>
>> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
>> index 62df71b13fa..2d78c1182fa 100644
>> --- a/gdb/configure.tgt
>> +++ b/gdb/configure.tgt
>> @@ -363,7 +363,7 @@ lm32-*-*)
>> loongarch*-*-linux*)
>> # Target: LoongArch running Linux
>> gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
>> - linux-tdep.o solib-svr4.o"
>> + linux-tdep.o solib-svr4.o linux-record.o"
>> ;;
>> m32c-*-*)
>> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
>> index 71578060303..86e7ed8a0bc 100644
>> --- a/gdb/loongarch-linux-tdep.c
>> +++ b/gdb/loongarch-linux-tdep.c
>> @@ -602,6 +602,9 @@ loongarch_linux_init_abi (struct gdbarch_info
>> info, struct gdbarch *gdbarch)
>> /* Get the syscall number from the arch's register. */
>> set_gdbarch_get_syscall_number (gdbarch,
>> loongarch_linux_get_syscall_number);
>> +
>> + /* Reversible debugging, process record. */
>> + set_gdbarch_process_record (gdbarch, loongarch_process_record);
>> }
>> /* Initialize LoongArch Linux target support. */
>> diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
>> index c50dd7f4b78..cf72c48b573 100644
>> --- a/gdb/loongarch-tdep.c
>> +++ b/gdb/loongarch-tdep.c
>> @@ -18,12 +18,16 @@
>> along with this program. If not, see
>> <http://www.gnu.org/licenses/>. */
>> #include "arch-utils.h"
>> +#include "arch/loongarch-insn.h"
>> #include "dwarf2/frame.h"
>> #include "elf-bfd.h"
>> #include "extract-store-integer.h"
>> #include "frame-unwind.h"
>> #include "gdbcore.h"
>> +#include "linux-record.h"
>> #include "loongarch-tdep.h"
>> +#include "record.h"
>> +#include "record-full.h"
>> #include "reggroups.h"
>> #include "target.h"
>> #include "target-descriptions.h"
>> @@ -1889,6 +1893,594 @@ loongarch_gdbarch_init (struct gdbarch_info
>> info, struct gdbarch_list *arches)
>> return gdbarch;
>> }
>> +/* LoongArch process record-replay related structures, defines etc. */
>> +
>> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int reg_len = LENGTH; \
>> + if (reg_len) \
>> + { \
>> + REGS = XNEWVEC (uint32_t, reg_len); \
>> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int mem_len = LENGTH; \
>> + if (mem_len) \
>> + { \
>> + MEMS = XNEWVEC (struct loongarch_mem_r, mem_len); \
>> + memcpy(&MEMS->len, &RECORD_BUF[0], \
>> + sizeof(struct loongarch_mem_r) * LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +/* LoongArch record/replay structures and enumerations. */
>> +
>> +struct loongarch_mem_r
>> +{
>> + uint64_t len; /* Record length. */
>> + uint64_t addr; /* Memory address. */
>> +};
>> +
>> +enum loongarch_record_result
>> +{
>> + LOONGARCH_RECORD_SUCCESS,
>> + LOONGARCH_RECORD_UNSUPPORTED,
>> + LOONGARCH_RECORD_UNKNOWN
>> +};
>> +
>> +struct loongarch_insn_record
>> +{
>> + struct gdbarch *gdbarch;
>> + struct regcache *regcache;
>> + CORE_ADDR this_addr; /* Addr of insn to be
>> recorded. */
>> + uint32_t insn; /* Insn to be
>> recorded. */
>> + uint32_t mem_rec_count; /* Count of memory
>> records. */
>> + uint32_t reg_rec_count; /* Count of register
>> records. */
>> + uint32_t *regs; /* Registers to be
>> recorded. */
>> + struct loongarch_mem_r *loongarch_mems; /* Memory location to be
>> recorded. */
>> +};
>
> Record-full is already infamous for being quite slow, and a significant
> part of it is due to dynamic memory allocation and reading inferior
> state (memory or registers). Your strategy here is doubling up the
> number of both allocations and accesses to the inferior. The code would
> perform much better if you just did the calls to the record-full
> functions instead of building it here first.
>
> Did you run into any troubles with that traditional approach that led
> you to design this strategy?
>
Thanks for your suggestion.
I will rewrite these code by calling record_full functions directly
in loongarch_record_xxxx_insn().
>> +
>> +/* Record handler for data processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_data_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rd;
>> + uint32_t record_buf[1];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for read time instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_read_time_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rd, rj;
>> + uint32_t record_buf[2];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + record_buf[1] = rj;
>> + loongarch_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for jump instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_jump_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + if (is_jirl_insn (loongarch_insn_r->insn))
>> + {
>> + int rd;
>> + uint32_t record_buf[1];
>> + rd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + record_buf[0] = rd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs,
>> loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if(is_bl_insn (loongarch_insn_r->insn))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = LOONGARCH_RA_REGNUM;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs,
>> loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for float data processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_float_data_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int fd;
>> + uint32_t record_buf[1];
>> + fd = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
>> + + LOONGARCH_FIRST_FP_REGNUM;
>> + record_buf[0] = fd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for fcsr processing instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_fcsr_proc_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int fcsr;
>> + uint32_t record_buf[1];
>> + fcsr = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0)
>> + + LOONGARCH_FCSR_REGNUM;
>> + record_buf[0] = fcsr;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition flag register processing
>> instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_fcc_proc_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + int cd, imm3_4;
>> + uint32_t record_buf[1];
>> + cd = loongarch_decode_imm ("0:3", loongarch_insn_r->insn, 0);
>> + imm3_4 = loongarch_decode_imm ("3:2", loongarch_insn_r->insn, 0);
>> + if (imm3_4 != 0)
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +
>> + record_buf[0] = cd;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for float instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_float_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + if (is_movgr2fcsr_insn (loongarch_insn_r->insn))
>> + return loongarch_record_fcsr_proc_insn (loongarch_insn_r);
>> + else if (is_mov2cf_insn (loongarch_insn_r->insn))
>> + return loongarch_record_fcc_proc_insn (loongarch_insn_r);
>> + else
>> + return loongarch_record_float_data_proc_insn (loongarch_insn_r);
>> +}
>> +
>> +/* Record handler for store instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_store_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + enum store_types
>> + {
>> + STB, STH, STW, STD, STXB, STXH, STXW, STXD, STPTRW, STPTRD,
>> + SCW, SCD, FSTS, FSTD, FSTXS, FSTXD, VST, XVST, NOT_STORE
>> + };
>> + int store_type;
>> + uint64_t record_buf_mem[2];
>> + store_type = is_stb_insn (loongarch_insn_r->insn) ? STB :
>> + is_sth_insn (loongarch_insn_r->insn) ? STH :
>> + is_stw_insn (loongarch_insn_r->insn) ? STW :
>> + is_std_insn (loongarch_insn_r->insn) ? STD :
>> + is_stxb_insn (loongarch_insn_r->insn) ? STXB :
>> + is_stxh_insn (loongarch_insn_r->insn) ? STXH :
>> + is_stxw_insn (loongarch_insn_r->insn) ? STXW :
>> + is_stxd_insn (loongarch_insn_r->insn) ? STXD :
>> + is_stptrw_insn (loongarch_insn_r->insn) ? STPTRW :
>> + is_stptrd_insn (loongarch_insn_r->insn) ? STPTRD :
>> + is_scw_insn (loongarch_insn_r->insn) ? SCW :
>> + is_scd_insn (loongarch_insn_r->insn) ? SCD :
>> + is_fsts_insn (loongarch_insn_r->insn) ? FSTS :
>> + is_fstd_insn (loongarch_insn_r->insn) ? FSTD :
>> + is_fstxs_insn (loongarch_insn_r->insn) ? FSTXS :
>> + is_fstxd_insn (loongarch_insn_r->insn) ? FSTXD :
>> + is_vst_insn (loongarch_insn_r->insn) ? VST :
>> + is_xvst_insn (loongarch_insn_r->insn) ? XVST :
>> + NOT_STORE;
>> +
>> + if (store_type == STB || store_type == STH || store_type == STW
>> + || store_type == STD || store_type == FSTS || store_type == FSTD
>> + || store_type == VST || store_type == XVST)
>> + {
>> + int rj_num;
>> + int data_size;
>> + int imm;
>> + uint64_t rj_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + imm = loongarch_decode_imm ("10:12", loongarch_insn_r->insn, 1);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + address = rj_val + imm;
>> + switch (store_type)
>> + {
>> + case STB:
>> + data_size = 1;
>> + break;
>> + case STH:
>> + data_size = 2;
>> + break;
>> + case STW:
>> + case FSTS:
>> + data_size = 4;
>> + break;
>> + case STD:
>> + case FSTD:
>> + data_size = 8;
>> + break;
>> + case VST:
>> + data_size = 16;
>> + break;
>> + case XVST:
>> + data_size = 32;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if (store_type == STXB || store_type == STXH || store_type ==
>> STXW
>> + || store_type == STXD || store_type == FSTXS || store_type ==
>> FSTXD)
>> + {
>> + int data_size;
>> + int rj_num, rk_num;
>> + uint64_t rj_val,rk_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num,
>> &rk_val);
>> + address = rj_val + rk_val;
>> + switch (store_type)
>> + {
>> + case STXB:
>> + data_size = 1;
>> + break;
>> + case STXH:
>> + data_size = 2;
>> + break;
>> + case STXW:
>> + case FSTXS:
>> + data_size = 4;
>> + break;
>> + case STXD:
>> + case FSTXD:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> + else if (store_type == STPTRW || store_type == STPTRD || store_type
>> == SCW
>> + || store_type == SCD)
>> + {
>> + int data_size;
>> + int rj_num;
>> + int imm;
>> + uint64_t rj_val;
>> + uint64_t address;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + imm = loongarch_decode_imm ("10:14<<2",
>> + loongarch_insn_r->insn, 1);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + address = rj_val + imm;
>> + switch (store_type)
>> + {
>> + case STPTRW:
>> + case SCW:
>> + data_size = 4;
>> + break;
>> + case STPTRD:
>> + case SCD:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> + }
>> +
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +}
>> +
>> +/* Record handler for atomic memory access instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_am_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + int rj_num, rd_num;
>> + int word_or_double;
>> + int data_size;
>> + uint64_t address;
>> + uint32_t record_buf[1];
>> + uint64_t record_buf_mem[2];
>> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + word_or_double = loongarch_decode_imm ("15:1",
>> + loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &address);
>> + data_size = word_or_double == 1 ? 8 : 4;
>> + record_buf[0] = rd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = address;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> loongarch_insn_r->mem_rec_count,
>> + record_buf_mem);
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition load instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_cond_load_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> + {
>> + int rd_num, rj_num, rk_num, fd_num;
>> + uint64_t rj_val, rk_val;
>> + rd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + fd_num = loongarch_decode_imm ("0:5", loongarch_insn_r->insn, 0);
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num,
>> &rk_val);
>> +
>> + if ((is_ldgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
>> + || (is_ldle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = rd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + }
>> + else if ((is_fldgt_insn (loongarch_insn_r->insn) && (rj_val >
>> rk_val))
>> + || (is_fldle_insn (loongarch_insn_r->insn) && (rj_val <=
>> rk_val)))
>> + {
>> + uint32_t record_buf[1];
>> + record_buf[0] = fd_num;
>> + loongarch_insn_r->reg_rec_count = 1;
>> +
>> + REG_ALLOC (loongarch_insn_r->regs, loongarch_insn_r->reg_rec_count,
>> + record_buf);
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for condition store instructions. */
>> +
>> +static unsigned int
>> +loongarch_record_cond_store_insn (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + int rj_num, rk_num;
>> + int data_size;
>> + uint64_t rj_val, rk_val;
>> + uint32_t length_opcode;
>> + rj_num = loongarch_decode_imm ("5:5", loongarch_insn_r->insn, 0);
>> + rk_num = loongarch_decode_imm ("10:5", loongarch_insn_r->insn, 0);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rj_num,
>> &rj_val);
>> + regcache_raw_read_unsigned (loongarch_insn_r->regcache, rk_num,
>> &rk_val);
>> +
>> + if ((is_stgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
>> + || (is_stle_insn (loongarch_insn_r->insn) && (rj_val <= rk_val)))
>> + {
>> + uint64_t record_buf_mem[2];
>> + length_opcode = loongarch_insn_r->insn & 0x00018000;
>> + switch (length_opcode)
>> + {
>> + case 0x00000000:
>> + data_size = 1;
>> + break;
>> + case 0x00008000:
>> + data_size = 2;
>> + break;
>> + case 0x00010000:
>> + data_size = 4;
>> + break;
>> + case 0x00018000:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = rj_val;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count, record_buf_mem);
>> + }
>> + else if ((is_fstgt_insn (loongarch_insn_r->insn) && (rj_val > rk_val))
>> + || (is_fstle_insn (loongarch_insn_r->insn) && (rj_val <=
>> rk_val)))
>> + {
>> + uint64_t record_buf_mem[2];
>> + length_opcode = loongarch_insn_r->insn & 0x00008000;
>> + switch (length_opcode)
>> + {
>> + case 0x00000000:
>> + data_size = 4;
>> + break;
>> + case 0x00008000:
>> + data_size = 8;
>> + break;
>> + default:
>> + data_size = 0;
>> + break;
>> + }
>> + record_buf_mem[0] = data_size;
>> + record_buf_mem[1] = rj_val;
>> + loongarch_insn_r->mem_rec_count = 1;
>> +
>> + MEM_ALLOC (loongarch_insn_r->loongarch_mems,
>> + loongarch_insn_r->mem_rec_count,record_buf_mem);
>> + }
>> +
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for special instructions like privilege instructions,
>> + barrier instructions and cache related instructions etc. */
>> +
>> +static unsigned int
>> +loongarch_record_special_insn (loongarch_insn_record *loongarch_insn_r)
>> +{
>> + return LOONGARCH_RECORD_SUCCESS;
>> +}
>> +
>> +/* Decode insns type and invoke its record handler. */
>> +
>> +static unsigned int
>> +loongarch_record_decode_insn_handler (loongarch_insn_record
>> *loongarch_insn_r)
>> +{
>> + if (is_data_process_insn (loongarch_insn_r->insn))
>> + return loongarch_record_data_proc_insn (loongarch_insn_r);
>> + else if (is_jump_insn (loongarch_insn_r->insn))
>> + return loongarch_record_jump_insn (loongarch_insn_r);
>> + else if (is_store_insn (loongarch_insn_r->insn))
>> + return loongarch_record_store_insn (loongarch_insn_r);
>> + else if (is_read_time_insn (loongarch_insn_r->insn))
>> + return loongarch_record_read_time_insn (loongarch_insn_r);
>> + else if (is_float_insn (loongarch_insn_r->insn))
>> + return loongarch_record_float_insn (loongarch_insn_r);
>> + else if (is_special_insn (loongarch_insn_r->insn))
>> + return loongarch_record_special_insn (loongarch_insn_r);
>> + else if (is_am_insn (loongarch_insn_r->insn))
>> + return loongarch_record_am_insn (loongarch_insn_r);
>> + else if (is_cond_load_insn (loongarch_insn_r->insn))
>> + return loongarch_record_cond_load_insn (loongarch_insn_r);
>> + else if (is_cond_store_insn (loongarch_insn_r->insn))
>> + return loongarch_record_cond_store_insn (loongarch_insn_r);
>> +
>> + return LOONGARCH_RECORD_UNSUPPORTED;
>> +}
>> +
>> +/* Parse the current instruction and record the values of the
>> registers and
>> + memory that will be changed in current instruction to
>> record_arch_list
>> + return -1 if something is wrong. */
>> +
>> +int
>> +loongarch_process_record (struct gdbarch *gdbarch, struct regcache
>> *regcache,
>> + CORE_ADDR insn_addr)
>> +{
>> + int rec_num = 0;
>> + uint32_t ret = 0;
>> + loongarch_insn_record loongarch_record;
>> +
>> + /* reset the content of loongarch_record */
>> + memset (&loongarch_record, 0, sizeof (loongarch_insn_record));
>> +
>> + /* write the loongarch_record */
>> + loongarch_record.gdbarch = gdbarch;
>> + loongarch_record.regcache = regcache;
>> + loongarch_record.this_addr = insn_addr;
>> +
>> + /* Get the current instruction */
>> + loongarch_record.insn = (uint32_t) loongarch_fetch_instruction
>> (insn_addr);
>> + ret = loongarch_record_decode_insn_handler (&loongarch_record);
>> + if (ret == LOONGARCH_RECORD_UNSUPPORTED)
>> + {
>> + gdb_printf (gdb_stderr,
>> + _("Process record does not support instruction "
>> + "0x%0x at address %s.\n"),
>> + loongarch_record.insn,
>> + paddress (gdbarch, insn_addr));
> When dealing with unsupported instructions, at least in x86, we use
> error, rather than gdb_printf to stderr. Using errors also ensure that a
> partially recorded instruction (which isn't the case yet, but should be)
> will be fully released by the caller of this function.
When dealing with unsupported instructions, loongarch_process_record()
call gdb_printf() and return -1, the function record_full_message call
error(). The function flow is as follows:
record_full_message()
{
...
ret = gdbarch_process_record()
->loongarch_process_record()
...
if (ret > 0)
error (_("Process record: inferior program stopped."));
if (ret < 0)
error (_("Process record: failed to record execution log."));
}
I see that other archs(includes x86) also use gdb_printf in
xxx_process_record() to print this message. And follow the same
processing flow.
https://sourceware.org/git?p=binutils-gdb.git;a=blob;f=gdb/i386-tdep.c;#l8155
https://sourceware.org/git?p=binutils-gdb.git;a=blob;f=gdb/aarch64-tdep.c;#l5977
https://sourceware.org/git?p=binutils-gdb.git;a=blob;f=gdb/s390-tdep.c;#l6796
So, it is no need to modify here, right?
Thanks,
Hui
>> + ret = -1;
>> + }
>> + if (ret == LOONGARCH_RECORD_SUCCESS)
>> + {
>> + /* Record registers. */
>> + record_full_arch_list_add_reg (loongarch_record.regcache,
>> + LOONGARCH_PC_REGNUM);
>> + if (loongarch_record.reg_rec_count)
>> + {
>> + for (rec_num = 0; rec_num < loongarch_record.reg_rec_count;
>> rec_num++)
>> + {
>> + if (record_full_arch_list_add_reg (loongarch_record.regcache,
>> + loongarch_record.regs[rec_num]))
>> + ret = -1;
>> + }
>> + }
>> +
>> + /* Record memories. */
>> + if (loongarch_record.mem_rec_count)
>> + {
>> + for (rec_num = 0; rec_num < loongarch_record.mem_rec_count;
>> rec_num++)
>> + {
>> + if (record_full_arch_list_add_mem
>> + ((CORE_ADDR)loongarch_record.loongarch_mems[rec_num].addr,
>> + loongarch_record.loongarch_mems[rec_num].len))
>> + ret = -1;
>> + }
>> + }
>> +
>> + if (record_full_arch_list_add_end ())
>> + ret = -1;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> void _initialize_loongarch_tdep ();
>> void
>> _initialize_loongarch_tdep ()
>> diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h
>> index 5c8108182ad..a148363c795 100644
>> --- a/gdb/loongarch-tdep.h
>> +++ b/gdb/loongarch-tdep.h
>> @@ -44,4 +44,7 @@ struct loongarch_gdbarch_tdep : gdbarch_tdep_base
>> CORE_ADDR (*syscall_next_pc) (const frame_info_ptr &frame) = nullptr;
>> };
>> +extern int loongarch_process_record (struct gdbarch *gdbarch,
>> + struct regcache *regcache, CORE_ADDR addr);
>> +
>> #endif /* LOONGARCH_TDEP_H */
>> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
>> index 410f99e3350..9b994a9f640 100644
>> --- a/gdb/testsuite/lib/gdb.exp
>> +++ b/gdb/testsuite/lib/gdb.exp
>> @@ -3698,6 +3698,7 @@ proc supports_process_record {} {
>> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
>> || [istarget "i\[34567\]86-*-linux*"]
>> || [istarget "aarch64*-*-linux*"]
>> + || [istarget "loongarch*-*-linux*"]
>> || [istarget "powerpc*-*-linux*"]
>> || [istarget "s390*-*-linux*"] } {
>> return 1
>> @@ -3717,6 +3718,7 @@ proc supports_reverse {} {
>> if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"]
>> || [istarget "i\[34567\]86-*-linux*"]
>> || [istarget "aarch64*-*-linux*"]
>> + || [istarget "loongarch*-*-linux*"]
>> || [istarget "powerpc*-*-linux*"]
>> || [istarget "s390*-*-linux*"] } {
>> return 1
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay
2024-11-13 13:01 ` Guinevere Larsen
@ 2024-11-19 13:22 ` Hui Li
0 siblings, 0 replies; 13+ messages in thread
From: Hui Li @ 2024-11-19 13:22 UTC (permalink / raw)
To: Guinevere Larsen, gdb-patches; +Cc: Tiezhu Yang
On 2024/11/13 下午9:01, Guinevere Larsen wrote:
> Hi!
>
> Again, I don't understand the loongarch specific parts, so I'll leave
> review of those for Tiezhu Yang. I did have a couple of general
> suggestions, but with those fixed, I'm happy to approve the reverse
> debugging parts of this patch!
>
> Approved-By: Guinevere Larsen <guinevere@redhat.com> (record-full)
>
Thanks for your reply.
I will modify all the relevant code based on your suggestions and send
v2 next few days.
Thanks,
Hui
> On 11/13/24 6:53 AM, Hui Li wrote:
>> The process record and replay function also need record Linux
>> system call instruction. This patch adds LoongArch system call
>> number definitions in gdb/arch/loongarch-syscall.h, and adds
>> loongarch_linux_syscall_record() in gdb/loongarch-linux-tdep.c
>> to record system call execute log. With this patch, the mainly
>> function of process record/replay and reverse debugging has been
> typo here. Do you mean "main functions" or "main functionality" ?
>> implemented.
>>
>> The LoongArch system call numbers definitions are obtained from Linux
>> kernel.
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h
>>
>>
>> Signed-off-by: Hui Li <lihui@loongson.cn>
>> ---
>> gdb/arch/loongarch-syscall.h | 348 +++++++++++++++++++++
>> gdb/loongarch-linux-tdep.c | 565 +++++++++++++++++++++++++++++++++++
>> gdb/loongarch-tdep.c | 18 ++
>> gdb/loongarch-tdep.h | 4 +
>> 4 files changed, 935 insertions(+)
>> create mode 100644 gdb/arch/loongarch-syscall.h
>>
>> diff --git a/gdb/arch/loongarch-syscall.h b/gdb/arch/loongarch-syscall.h
>> new file mode 100644
>> index 00000000000..6f10b1d33e7
>> --- /dev/null
>> +++ b/gdb/arch/loongarch-syscall.h
>> @@ -0,0 +1,348 @@
>> +/* Target-dependent code for LoongArch
>> +
>> + Copyright (C) 2024 Free Software Foundation, Inc.
>> +
>> + This program is free software; you can redistribute it and/or modify
>> + it under the terms of the GNU General Public License as published by
>> + the Free Software Foundation; either version 3 of the License, or
>> + (at your option) any later version.
>> +
>> + This program is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + GNU General Public License for more details.
>> +
>> + You should have received a copy of the GNU General Public License
>> + along with this program. If not, see
>> <http://www.gnu.org/licenses/>. */
>> +
>> +/* The syscall number definitions are obtained from Linux kernel
>> header file.
>> +
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h
>>
>> +
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/unistd.h
>> */
>> +
>> +#ifndef ARCH_LOONGARCH_SYSCALL_H
>> +#define ARCH_LOONGARCH_SYSCALL_H
>> +
>> +enum loongarch_syscall
>> +{
>> + loongarch_sys_io_setup = 0,
>> + loongarch_sys_io_destroy = 1,
>> + loongarch_sys_io_submit = 2,
>> + loongarch_sys_io_cancel = 3,
>> + loongarch_sys_io_getevents = 4,
>> + loongarch_sys_setxattr = 5,
>> + loongarch_sys_lsetxattr = 6,
>> + loongarch_sys_fsetxattr = 7,
>> + loongarch_sys_getxattr = 8,
>> + loongarch_sys_lgetxattr = 9,
>> + loongarch_sys_fgetxattr = 10,
>> + loongarch_sys_listxattr = 11,
>> + loongarch_sys_llistxattr = 12,
>> + loongarch_sys_flistxattr = 13,
>> + loongarch_sys_removexattr = 14,
>> + loongarch_sys_lremovexattr = 15,
>> + loongarch_sys_fremovexattr = 16,
>> + loongarch_sys_getcwd = 17,
>> + loongarch_sys_lookup_dcookie = 18,
>> + loongarch_sys_eventfd2 = 19,
>> + loongarch_sys_epoll_create1 = 20,
>> + loongarch_sys_epoll_ctl = 21,
>> + loongarch_sys_epoll_pwait = 22,
>> + loongarch_sys_dup = 23,
>> + loongarch_sys_dup3 = 24,
>> + loongarch_sys_fcntl = 25,
>> + loongarch_sys_inotify_init1 = 26,
>> + loongarch_sys_inotify_add_watch = 27,
>> + loongarch_sys_inotify_rm_watch = 28,
>> + loongarch_sys_ioctl = 29,
>> + loongarch_sys_ioprio_set = 30,
>> + loongarch_sys_ioprio_get = 31,
>> + loongarch_sys_flock = 32,
>> + loongarch_sys_mknodat = 33,
>> + loongarch_sys_mkdirat = 34,
>> + loongarch_sys_unlinkat = 35,
>> + loongarch_sys_symlinkat = 36,
>> + loongarch_sys_linkat = 37,
>> +
>> + loongarch_sys_umount2 = 39,
>> + loongarch_sys_mount = 40,
>> + loongarch_sys_pivot_root = 41,
>> + loongarch_sys_nfsservctl = 42,
>> + loongarch_sys_statfs = 43,
>> + loongarch_sys_fstatfs = 44,
>> + loongarch_sys_truncate = 45,
>> + loongarch_sys_ftruncate = 46,
>> + loongarch_sys_fallocate = 47,
>> + loongarch_sys_faccessat = 48,
>> + loongarch_sys_chdir = 49,
>> + loongarch_sys_fchdir = 50,
>> + loongarch_sys_chroot = 51,
>> + loongarch_sys_fchmod = 52,
>> + loongarch_sys_fchmodat = 53,
>> + loongarch_sys_fchownat = 54,
>> + loongarch_sys_fchown = 55,
>> + loongarch_sys_openat = 56,
>> + loongarch_sys_close = 57,
>> + loongarch_sys_vhangup = 58,
>> + loongarch_sys_pipe2 = 59,
>> + loongarch_sys_quotactl = 60,
>> + loongarch_sys_getdents64 = 61,
>> + loongarch_sys_lseek = 62,
>> + loongarch_sys_read = 63,
>> + loongarch_sys_write = 64,
>> + loongarch_sys_readv = 65,
>> + loongarch_sys_writev = 66,
>> + loongarch_sys_pread64 = 67,
>> + loongarch_sys_pwrite64 = 68,
>> + loongarch_sys_preadv = 69,
>> + loongarch_sys_pwritev = 70,
>> + loongarch_sys_sendfile = 71,
>> + loongarch_sys_pselect6 = 72,
>> + loongarch_sys_ppoll = 73,
>> + loongarch_sys_signalfd4 = 74,
>> + loongarch_sys_vmsplice = 75,
>> + loongarch_sys_splice = 76,
>> + loongarch_sys_tee = 77,
>> + loongarch_sys_readlinkat = 78,
>> + loongarch_sys_newfstatat = 79,
>> + loongarch_sys_fstat = 80,
>> + loongarch_sys_sync = 81,
>> + loongarch_sys_fsync = 82,
>> + loongarch_sys_fdatasync = 83,
>> + loongarch_sys_sync_file_range = 84,
>> + loongarch_sys_timerfd_create = 85,
>> + loongarch_sys_timerfd_settime = 86,
>> + loongarch_sys_timerfd_gettime = 87,
>> + loongarch_sys_utimensat = 88,
>> + loongarch_sys_acct = 89,
>> + loongarch_sys_capget = 90,
>> + loongarch_sys_capset = 91,
>> + loongarch_sys_personality = 92,
>> + loongarch_sys_exit = 93,
>> + loongarch_sys_exit_group = 94,
>> + loongarch_sys_waitid = 95,
>> + loongarch_sys_set_tid_address = 96,
>> + loongarch_sys_unshare = 97,
>> + loongarch_sys_futex = 98,
>> + loongarch_sys_set_robust_list = 99,
>> + loongarch_sys_get_robust_list = 100,
>> + loongarch_sys_nanosleep = 101,
>> + loongarch_sys_getitimer = 102,
>> + loongarch_sys_setitimer = 103,
>> + loongarch_sys_kexec_load = 104,
>> + loongarch_sys_init_module = 105,
>> + loongarch_sys_delete_module = 106,
>> + loongarch_sys_timer_create = 107,
>> + loongarch_sys_timer_gettime = 108,
>> + loongarch_sys_timer_getoverrun = 109,
>> + loongarch_sys_timer_settime = 110,
>> + loongarch_sys_timer_delete = 111,
>> + loongarch_sys_clock_settime = 112,
>> + loongarch_sys_clock_gettime = 113,
>> + loongarch_sys_clock_getres = 114,
>> + loongarch_sys_clock_nanosleep = 115,
>> + loongarch_sys_syslog = 116,
>> + loongarch_sys_ptrace = 117,
>> + loongarch_sys_sched_setparam = 118,
>> + loongarch_sys_sched_setscheduler = 119,
>> + loongarch_sys_sched_getscheduler = 120,
>> + loongarch_sys_sched_getparam = 121,
>> + loongarch_sys_sched_setaffinity = 122,
>> + loongarch_sys_sched_getaffinity = 123,
>> + loongarch_sys_sched_yield = 124,
>> + loongarch_sys_sched_get_priority_max = 125,
>> + loongarch_sys_sched_get_priority_min = 126,
>> + loongarch_sys_sched_rr_get_interval = 127,
>> + loongarch_sys_restart_syscall = 128,
>> + loongarch_sys_kill = 129,
>> + loongarch_sys_tkill = 130,
>> + loongarch_sys_tgkill = 131,
>> + loongarch_sys_sigaltstack = 132,
>> + loongarch_sys_rt_sigsuspend = 133,
>> + loongarch_sys_rt_sigaction = 134,
>> + loongarch_sys_rt_sigprocmask = 135,
>> + loongarch_sys_rt_sigpending = 136,
>> + loongarch_sys_rt_sigtimedwait = 137,
>> + loongarch_sys_rt_sigqueueinfo = 138,
>> + loongarch_sys_rt_sigreturn = 139,
>> + loongarch_sys_setpriority = 140,
>> + loongarch_sys_getpriority = 141,
>> + loongarch_sys_reboot = 142,
>> + loongarch_sys_setregid = 143,
>> + loongarch_sys_setgid = 144,
>> + loongarch_sys_setreuid = 145,
>> + loongarch_sys_setuid = 146,
>> + loongarch_sys_setresuid = 147,
>> + loongarch_sys_getresuid = 148,
>> + loongarch_sys_setresgid = 149,
>> + loongarch_sys_getresgid = 150,
>> + loongarch_sys_setfsuid = 151,
>> + loongarch_sys_setfsgid = 152,
>> + loongarch_sys_times = 153,
>> + loongarch_sys_setpgid = 154,
>> + loongarch_sys_getpgid = 155,
>> + loongarch_sys_getsid = 156,
>> + loongarch_sys_setsid = 157,
>> + loongarch_sys_getgroups = 158,
>> + loongarch_sys_setgroups = 159,
>> + loongarch_sys_uname = 160,
>> + loongarch_sys_sethostname = 161,
>> + loongarch_sys_setdomainname = 162,
>> +
>> + loongarch_sys_getrusage = 165,
>> + loongarch_sys_umask = 166,
>> + loongarch_sys_prctl = 167,
>> + loongarch_sys_getcpu = 168,
>> + loongarch_sys_gettimeofday = 169,
>> + loongarch_sys_settimeofday = 170,
>> + loongarch_sys_adjtimex = 171,
>> + loongarch_sys_getpid = 172,
>> + loongarch_sys_getppid = 173,
>> + loongarch_sys_getuid = 174,
>> + loongarch_sys_geteuid = 175,
>> + loongarch_sys_getgid = 176,
>> + loongarch_sys_getegid = 177,
>> + loongarch_sys_gettid = 178,
>> + loongarch_sys_sysinfo = 179,
>> + loongarch_sys_mq_open = 180,
>> + loongarch_sys_mq_unlink = 181,
>> + loongarch_sys_mq_timedsend = 182,
>> + loongarch_sys_mq_timedreceive = 183,
>> + loongarch_sys_mq_notify = 184,
>> + loongarch_sys_mq_getsetattr = 185,
>> + loongarch_sys_msgget = 186,
>> + loongarch_sys_msgctl = 187,
>> + loongarch_sys_msgrcv = 188,
>> + loongarch_sys_msgsnd = 189,
>> + loongarch_sys_semget = 190,
>> + loongarch_sys_semctl = 191,
>> + loongarch_sys_semtimedop = 192,
>> + loongarch_sys_semop = 193,
>> + loongarch_sys_shmget = 194,
>> + loongarch_sys_shmctl = 195,
>> + loongarch_sys_shmat = 196,
>> + loongarch_sys_shmdt = 197,
>> + loongarch_sys_socket = 198,
>> + loongarch_sys_socketpair = 199,
>> + loongarch_sys_bind = 200,
>> + loongarch_sys_listen = 201,
>> + loongarch_sys_accept = 202,
>> + loongarch_sys_connect = 203,
>> + loongarch_sys_getsockname = 204,
>> + loongarch_sys_getpeername = 205,
>> + loongarch_sys_sendto = 206,
>> + loongarch_sys_recvfrom = 207,
>> + loongarch_sys_setsockopt = 208,
>> + loongarch_sys_getsockopt = 209,
>> + loongarch_sys_shutdown = 210,
>> + loongarch_sys_sendmsg = 211,
>> + loongarch_sys_recvmsg = 212,
>> + loongarch_sys_readahead = 213,
>> + loongarch_sys_brk = 214,
>> + loongarch_sys_munmap = 215,
>> + loongarch_sys_mremap = 216,
>> + loongarch_sys_add_key = 217,
>> + loongarch_sys_request_key = 218,
>> + loongarch_sys_keyctl = 219,
>> + loongarch_sys_clone = 220,
>> + loongarch_sys_execve = 221,
>> + loongarch_sys_mmap = 222,
>> + loongarch_sys_fadvise64 = 223,
>> + loongarch_sys_swapon = 224,
>> + loongarch_sys_swapoff = 225,
>> + loongarch_sys_mprotect = 226,
>> + loongarch_sys_msync = 227,
>> + loongarch_sys_mlock = 228,
>> + loongarch_sys_munlock = 229,
>> + loongarch_sys_mlockall = 230,
>> + loongarch_sys_munlockall = 231,
>> + loongarch_sys_mincore = 232,
>> + loongarch_sys_madvise = 233,
>> + loongarch_sys_remap_file_pages = 234,
>> + loongarch_sys_mbind = 235,
>> + loongarch_sys_get_mempolicy = 236,
>> + loongarch_sys_set_mempolicy = 237,
>> + loongarch_sys_migrate_pages = 238,
>> + loongarch_sys_move_pages = 239,
>> + loongarch_sys_rt_tgsigqueueinfo = 240,
>> + loongarch_sys_perf_event_open = 241,
>> + loongarch_sys_accept4 = 242,
>> + loongarch_sys_recvmmsg = 243,
>> + loongarch_sys_wait4 = 260,
>> + loongarch_sys_prlimit64 = 261,
>> + loongarch_sys_fanotify_init = 262,
>> + loongarch_sys_fanotify_mark = 263,
>> + loongarch_sys_name_to_handle_at = 264,
>> + loongarch_sys_open_by_handle_at = 265,
>> + loongarch_sys_clock_adjtime = 266,
>> + loongarch_sys_syncfs = 267,
>> + loongarch_sys_setns = 268,
>> + loongarch_sys_sendmmsg = 269,
>> + loongarch_sys_process_vm_readv = 270,
>> + loongarch_sys_process_vm_writev = 271,
>> + loongarch_sys_kcmp = 272,
>> + loongarch_sys_finit_module = 273,
>> + loongarch_sys_sched_setattr = 274,
>> + loongarch_sys_sched_getattr = 275,
>> + loongarch_sys_renameat2 = 276,
>> + loongarch_sys_seccomp = 277,
>> + loongarch_sys_getrandom = 278,
>> + loongarch_sys_memfd_create = 279,
>> + loongarch_sys_bpf = 280,
>> + loongarch_sys_execveat = 281,
>> + loongarch_sys_userfaultfd = 282,
>> + loongarch_sys_membarrier = 283,
>> + loongarch_sys_mlock2 = 284,
>> + loongarch_sys_copy_file_range = 285,
>> + loongarch_sys_preadv2 = 286,
>> + loongarch_sys_pwritev2 = 287,
>> + loongarch_sys_pkey_mprotect = 288,
>> + loongarch_sys_pkey_alloc = 289,
>> + loongarch_sys_pkey_free = 290,
>> + loongarch_sys_statx = 291,
>> + loongarch_sys_io_pgetevents = 292,
>> + loongarch_sys_rseq = 293,
>> + loongarch_sys_kexec_file_load = 294,
>> +
>> + loongarch_sys_pidfd_send_signal = 424,
>> + loongarch_sys_io_uring_setup = 425,
>> + loongarch_sys_io_uring_enter = 426,
>> + loongarch_sys_io_uring_register = 427,
>> + loongarch_sys_open_tree = 428,
>> + loongarch_sys_move_mount = 429,
>> + loongarch_sys_fsopen = 430,
>> + loongarch_sys_fsconfig = 431,
>> + loongarch_sys_fsmount = 432,
>> + loongarch_sys_fspick = 433,
>> + loongarch_sys_pidfd_open = 434,
>> + loongarch_sys_clone3 = 435,
>> + loongarch_sys_close_range = 436,
>> + loongarch_sys_openat2 = 437,
>> + loongarch_sys_pidfd_getfd = 438,
>> + loongarch_sys_faccessat2 = 439,
>> + loongarch_sys_process_madvise = 440,
>> + loongarch_sys_epoll_pwait2 = 441,
>> + loongarch_sys_mount_setattr = 442,
>> + loongarch_sys_quotactl_fd = 443,
>> + loongarch_sys_landlock_create_ruleset = 444,
>> + loongarch_sys_landlock_add_rule = 445,
>> + loongarch_sys_landlock_restrict_self = 446,
>> +
>> + loongarch_sys_process_mrelease = 448,
>> + loongarch_sys_futex_waitv = 449,
>> + loongarch_sys_set_mempolicy_home_node = 450,
>> + loongarch_sys_cachestat = 451,
>> + loongarch_sys_fchmodat2 = 452,
>> + loongarch_sys_map_shadow_stack = 453,
>> + loongarch_sys_futex_wake = 454,
>> + loongarch_sys_futex_wait = 455,
>> + loongarch_sys_futex_requeue = 456,
>> + loongarch_sys_statmount = 457,
>> + loongarch_sys_listmount = 458,
>> + loongarch_sys_lsm_get_self_attr = 459,
>> + loongarch_sys_lsm_set_self_attr = 460,
>> + loongarch_sys_lsm_list_modules = 461,
>> + loongarch_sys_mseal = 462,
>> + loongarch_sys_syscalls = 463,
>> +};
>> +
>> +#endif /* ARCH_LOONGARCH_INSN_H */
>> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
>> index 86e7ed8a0bc..a027edd07e5 100644
>> --- a/gdb/loongarch-linux-tdep.c
>> +++ b/gdb/loongarch-linux-tdep.c
>> @@ -18,15 +18,21 @@
>> You should have received a copy of the GNU General Public License
>> along with this program. If not, see
>> <http://www.gnu.org/licenses/>. */
>> +#include "arch/loongarch-syscall.h"
>> #include "extract-store-integer.h"
>> +#include "gdbarch.h"
>> #include "glibc-tdep.h"
>> #include "inferior.h"
>> +#include "linux-record.h"
>> #include "linux-tdep.h"
>> #include "loongarch-tdep.h"
>> +#include "record-full.h"
>> +#include "regset.h"
>> #include "solib-svr4.h"
>> #include "target-descriptions.h"
>> #include "trad-frame.h"
>> #include "tramp-frame.h"
>> +#include "value.h"
>> #include "xml-syscall.h"
>> /* The syscall's XML filename for LoongArch. */
>> @@ -566,6 +572,561 @@ loongarch_linux_get_syscall_number (struct
>> gdbarch *gdbarch, thread_info *thread
>> return ret;
>> }
>> +static linux_record_tdep loongarch_linux_record_tdep;
>> +
>> +/* loongarch_canonicalize_syscall maps syscall ids from the native
>> LoongArch
>> + linux set of syscall ids into a canonical set of syscall ids used by
>> + process record. */
>> +
>> +static enum gdb_syscall
>> +loongarch_canonicalize_syscall (enum loongarch_syscall syscall_number)
>> +{
>> +#define SYSCALL_MAP(SYSCALL) case
>> loongarch_sys_##SYSCALL: \
>> + return gdb_sys_##SYSCALL
>> +
>> +#define UNSUPPORTED_SYSCALL_MAP(SYSCALL) case
>> loongarch_sys_##SYSCALL: \
>> + return gdb_sys_no_syscall
>> +
>> + switch(syscall_number)
>> + {
>> + SYSCALL_MAP (io_setup);
>> + SYSCALL_MAP (io_destroy);
>> + SYSCALL_MAP (io_submit);
>> + SYSCALL_MAP (io_cancel);
>> + SYSCALL_MAP (io_getevents);
>> + SYSCALL_MAP (setxattr);
>> + SYSCALL_MAP (lsetxattr);
>> + SYSCALL_MAP (fsetxattr);
>> + SYSCALL_MAP (getxattr);
>> + SYSCALL_MAP (lgetxattr);
>> + SYSCALL_MAP (fgetxattr);
>> + SYSCALL_MAP (listxattr);
>> + SYSCALL_MAP (llistxattr);
>> + SYSCALL_MAP (flistxattr);
>> + SYSCALL_MAP (removexattr);
>> + SYSCALL_MAP (lremovexattr);
>> + SYSCALL_MAP (fremovexattr);
>> + SYSCALL_MAP (getcwd);
>> + SYSCALL_MAP (lookup_dcookie);
>> + SYSCALL_MAP (eventfd2);
>> + SYSCALL_MAP (epoll_create1);
>> + SYSCALL_MAP (epoll_ctl);
>> + SYSCALL_MAP (epoll_pwait);
>> + SYSCALL_MAP (dup);
>> + SYSCALL_MAP (dup3);
>> + SYSCALL_MAP (fcntl);
>> + SYSCALL_MAP (inotify_init1);
>> + SYSCALL_MAP (inotify_add_watch);
>> + SYSCALL_MAP (inotify_rm_watch);
>> + SYSCALL_MAP (ioctl);
>> + SYSCALL_MAP (ioprio_set);
>> + SYSCALL_MAP (ioprio_get);
>> + SYSCALL_MAP (flock);
>> + SYSCALL_MAP (mknodat);
>> + SYSCALL_MAP (mkdirat);
>> + SYSCALL_MAP (unlinkat);
>> + SYSCALL_MAP (symlinkat);
>> + SYSCALL_MAP (linkat);
>> + UNSUPPORTED_SYSCALL_MAP (umount2);
>> + SYSCALL_MAP (mount);
>> + SYSCALL_MAP (pivot_root);
>> + SYSCALL_MAP (nfsservctl);
>> + SYSCALL_MAP (statfs);
>> + SYSCALL_MAP (truncate);
>> + SYSCALL_MAP (ftruncate);
>> + SYSCALL_MAP (fallocate);
>> + SYSCALL_MAP (faccessat);
>> + SYSCALL_MAP (fchdir);
>> + SYSCALL_MAP (chroot);
>> + SYSCALL_MAP (fchmod);
>> + SYSCALL_MAP (fchmodat);
>> + SYSCALL_MAP (fchownat);
>> + SYSCALL_MAP (fchown);
>> + SYSCALL_MAP (openat);
>> + SYSCALL_MAP (close);
>> + SYSCALL_MAP (vhangup);
>> + SYSCALL_MAP (pipe2);
>> + SYSCALL_MAP (quotactl);
>> + SYSCALL_MAP (getdents64);
>> + SYSCALL_MAP (lseek);
>> + SYSCALL_MAP (read);
>> + SYSCALL_MAP (write);
>> + SYSCALL_MAP (readv);
>> + SYSCALL_MAP (writev);
>> + SYSCALL_MAP (pread64);
>> + SYSCALL_MAP (pwrite64);
>> + UNSUPPORTED_SYSCALL_MAP (preadv);
>> + UNSUPPORTED_SYSCALL_MAP (pwritev);
>> + SYSCALL_MAP (sendfile);
>> + SYSCALL_MAP (pselect6);
>> + SYSCALL_MAP (ppoll);
>> + UNSUPPORTED_SYSCALL_MAP (signalfd4);
>> + SYSCALL_MAP (vmsplice);
>> + SYSCALL_MAP (splice);
>> + SYSCALL_MAP (tee);
>> + SYSCALL_MAP (readlinkat);
>> + SYSCALL_MAP (newfstatat);
>> + SYSCALL_MAP (fstat);
>> + SYSCALL_MAP (sync);
>> + SYSCALL_MAP (fsync);
>> + SYSCALL_MAP (fdatasync);
>> + SYSCALL_MAP (sync_file_range);
>> + UNSUPPORTED_SYSCALL_MAP (timerfd_create);
>> + UNSUPPORTED_SYSCALL_MAP (timerfd_settime);
>> + UNSUPPORTED_SYSCALL_MAP (timerfd_gettime);
>> + UNSUPPORTED_SYSCALL_MAP (utimensat);
>> + SYSCALL_MAP (acct);
>> + SYSCALL_MAP (capget);
>> + SYSCALL_MAP (capset);
>> + SYSCALL_MAP (personality);
>> + SYSCALL_MAP (exit);
>> + SYSCALL_MAP (exit_group);
>> + SYSCALL_MAP (waitid);
>> + SYSCALL_MAP (set_tid_address);
>> + SYSCALL_MAP (unshare);
>> + SYSCALL_MAP (futex);
>> + SYSCALL_MAP (set_robust_list);
>> + SYSCALL_MAP (get_robust_list);
>> + SYSCALL_MAP (nanosleep);
>> + SYSCALL_MAP (getitimer);
>> + SYSCALL_MAP (setitimer);
>> + SYSCALL_MAP (kexec_load);
>> + SYSCALL_MAP (init_module);
>> + SYSCALL_MAP (delete_module);
>> + SYSCALL_MAP (timer_create);
>> + SYSCALL_MAP (timer_settime);
>> + SYSCALL_MAP (timer_gettime);
>> + SYSCALL_MAP (timer_getoverrun);
>> + SYSCALL_MAP (timer_delete);
>> + SYSCALL_MAP (clock_settime);
>> + SYSCALL_MAP (clock_gettime);
>> + SYSCALL_MAP (clock_getres);
>> + SYSCALL_MAP (clock_nanosleep);
>> + SYSCALL_MAP (syslog);
>> + SYSCALL_MAP (ptrace);
>> + SYSCALL_MAP (sched_setparam);
>> + SYSCALL_MAP (sched_setscheduler);
>> + SYSCALL_MAP (sched_getscheduler);
>> + SYSCALL_MAP (sched_getparam);
>> + SYSCALL_MAP (sched_setaffinity);
>> + SYSCALL_MAP (sched_getaffinity);
>> + SYSCALL_MAP (sched_yield);
>> + SYSCALL_MAP (sched_get_priority_max);
>> + SYSCALL_MAP (sched_get_priority_min);
>> + SYSCALL_MAP (sched_rr_get_interval);
>> + SYSCALL_MAP (kill);
>> + SYSCALL_MAP (tkill);
>> + SYSCALL_MAP (tgkill);
>> + SYSCALL_MAP (sigaltstack);
>> + SYSCALL_MAP (rt_sigsuspend);
>> + SYSCALL_MAP (rt_sigaction);
>> + SYSCALL_MAP (rt_sigprocmask);
>> + SYSCALL_MAP (rt_sigpending);
>> + SYSCALL_MAP (rt_sigtimedwait);
>> + SYSCALL_MAP (rt_sigqueueinfo);
>> + SYSCALL_MAP (rt_sigreturn);
>> + SYSCALL_MAP (setpriority);
>> + SYSCALL_MAP (getpriority);
>> + SYSCALL_MAP (reboot);
>> + SYSCALL_MAP (setregid);
>> + SYSCALL_MAP (setgid);
>> + SYSCALL_MAP (setreuid);
>> + SYSCALL_MAP (setuid);
>> + SYSCALL_MAP (setresuid);
>> + SYSCALL_MAP (getresuid);
>> + SYSCALL_MAP (setresgid);
>> + SYSCALL_MAP (getresgid);
>> + SYSCALL_MAP (setfsuid);
>> + SYSCALL_MAP (setfsgid);
>> + SYSCALL_MAP (times);
>> + SYSCALL_MAP (setpgid);
>> + SYSCALL_MAP (getpgid);
>> + SYSCALL_MAP (getsid);
>> + SYSCALL_MAP (setsid);
>> + SYSCALL_MAP (getgroups);
>> + SYSCALL_MAP (setgroups);
>> + SYSCALL_MAP (uname);
>> + SYSCALL_MAP (sethostname);
>> + SYSCALL_MAP (setdomainname);
>> + SYSCALL_MAP (getrusage);
>> + SYSCALL_MAP (umask);
>> + SYSCALL_MAP (prctl);
>> + SYSCALL_MAP (getcpu);
>> + SYSCALL_MAP (gettimeofday);
>> + SYSCALL_MAP (settimeofday);
>> + SYSCALL_MAP (adjtimex);
>> + SYSCALL_MAP (getpid);
>> + SYSCALL_MAP (getppid);
>> + SYSCALL_MAP (getuid);
>> + SYSCALL_MAP (geteuid);
>> + SYSCALL_MAP (getgid);
>> + SYSCALL_MAP (getegid);
>> + SYSCALL_MAP (gettid);
>> + SYSCALL_MAP (sysinfo);
>> + SYSCALL_MAP (mq_open);
>> + SYSCALL_MAP (mq_unlink);
>> + SYSCALL_MAP (mq_timedsend);
>> + SYSCALL_MAP (mq_timedreceive);
>> + SYSCALL_MAP (mq_notify);
>> + SYSCALL_MAP (mq_getsetattr);
>> + SYSCALL_MAP (msgget);
>> + SYSCALL_MAP (msgctl);
>> + SYSCALL_MAP (msgrcv);
>> + SYSCALL_MAP (msgsnd);
>> + SYSCALL_MAP (semget);
>> + SYSCALL_MAP (semctl);
>> + SYSCALL_MAP (semtimedop);
>> + SYSCALL_MAP (semop);
>> + SYSCALL_MAP (shmget);
>> + SYSCALL_MAP (shmctl);
>> + SYSCALL_MAP (shmat);
>> + SYSCALL_MAP (shmdt);
>> + SYSCALL_MAP (socket);
>> + SYSCALL_MAP (socketpair);
>> + SYSCALL_MAP (bind);
>> + SYSCALL_MAP (listen);
>> + SYSCALL_MAP (accept);
>> + SYSCALL_MAP (connect);
>> + SYSCALL_MAP (getsockname);
>> + SYSCALL_MAP (getpeername);
>> + SYSCALL_MAP (sendto);
>> + SYSCALL_MAP (recvfrom);
>> + SYSCALL_MAP (setsockopt);
>> + SYSCALL_MAP (getsockopt);
>> + SYSCALL_MAP (shutdown);
>> + SYSCALL_MAP (sendmsg);
>> + SYSCALL_MAP (recvmsg);
>> + SYSCALL_MAP (readahead);
>> + SYSCALL_MAP (brk);
>> + SYSCALL_MAP (munmap);
>> + SYSCALL_MAP (mremap);
>> + SYSCALL_MAP (add_key);
>> + SYSCALL_MAP (request_key);
>> + SYSCALL_MAP (keyctl);
>> + SYSCALL_MAP (clone);
>> + SYSCALL_MAP (execve);
>> +
>> + case loongarch_sys_mmap:
>> + return gdb_sys_mmap2;
>> +
>> + SYSCALL_MAP (fadvise64);
>> + SYSCALL_MAP (swapon);
>> + SYSCALL_MAP (swapoff);
>> + SYSCALL_MAP (mprotect);
>> + SYSCALL_MAP (msync);
>> + SYSCALL_MAP (mlock);
>> + SYSCALL_MAP (munlock);
>> + SYSCALL_MAP (mlockall);
>> + SYSCALL_MAP (munlockall);
>> + SYSCALL_MAP (mincore);
>> + SYSCALL_MAP (madvise);
>> + SYSCALL_MAP (remap_file_pages);
>> + SYSCALL_MAP (mbind);
>> + SYSCALL_MAP (get_mempolicy);
>> + SYSCALL_MAP (set_mempolicy);
>> + SYSCALL_MAP (migrate_pages);
>> + SYSCALL_MAP (move_pages);
>> + UNSUPPORTED_SYSCALL_MAP (rt_tgsigqueueinfo);
>> + UNSUPPORTED_SYSCALL_MAP (perf_event_open);
>> + UNSUPPORTED_SYSCALL_MAP (accept4);
>> + UNSUPPORTED_SYSCALL_MAP (recvmmsg);
>> + SYSCALL_MAP (wait4);
>> + UNSUPPORTED_SYSCALL_MAP (prlimit64);
>> + UNSUPPORTED_SYSCALL_MAP (fanotify_init);
>> + UNSUPPORTED_SYSCALL_MAP (fanotify_mark);
>> + UNSUPPORTED_SYSCALL_MAP (name_to_handle_at);
>> + UNSUPPORTED_SYSCALL_MAP (open_by_handle_at);
>> + UNSUPPORTED_SYSCALL_MAP (clock_adjtime);
>> + UNSUPPORTED_SYSCALL_MAP (syncfs);
>> + UNSUPPORTED_SYSCALL_MAP (setns);
>> + UNSUPPORTED_SYSCALL_MAP (sendmmsg);
>> + UNSUPPORTED_SYSCALL_MAP (process_vm_readv);
>> + UNSUPPORTED_SYSCALL_MAP (process_vm_writev);
>> + UNSUPPORTED_SYSCALL_MAP (kcmp);
>> + UNSUPPORTED_SYSCALL_MAP (finit_module);
>> + UNSUPPORTED_SYSCALL_MAP (sched_setattr);
>> + UNSUPPORTED_SYSCALL_MAP (sched_getattr);
>> + UNSUPPORTED_SYSCALL_MAP (renameat2);
>> + UNSUPPORTED_SYSCALL_MAP (seccomp);
>> + SYSCALL_MAP (getrandom);
>> + UNSUPPORTED_SYSCALL_MAP (memfd_create);
>> + UNSUPPORTED_SYSCALL_MAP (bpf);
>> + UNSUPPORTED_SYSCALL_MAP (execveat);
>> + UNSUPPORTED_SYSCALL_MAP (userfaultfd);
>> + UNSUPPORTED_SYSCALL_MAP (membarrier);
>> + UNSUPPORTED_SYSCALL_MAP (mlock2);
>> + UNSUPPORTED_SYSCALL_MAP (copy_file_range);
>> + UNSUPPORTED_SYSCALL_MAP (preadv2);
>> + UNSUPPORTED_SYSCALL_MAP (pwritev2);
>> + UNSUPPORTED_SYSCALL_MAP (pkey_mprotect);
>> + UNSUPPORTED_SYSCALL_MAP (pkey_alloc);
>> + UNSUPPORTED_SYSCALL_MAP (pkey_free);
>> + SYSCALL_MAP (statx);
>> + UNSUPPORTED_SYSCALL_MAP (io_pgetevents);
>> + UNSUPPORTED_SYSCALL_MAP (rseq);
>> + UNSUPPORTED_SYSCALL_MAP (kexec_file_load);
>> + UNSUPPORTED_SYSCALL_MAP (pidfd_send_signal);
>> + UNSUPPORTED_SYSCALL_MAP (io_uring_setup);
>> + UNSUPPORTED_SYSCALL_MAP (io_uring_enter);
>> + UNSUPPORTED_SYSCALL_MAP (io_uring_register);
>> + UNSUPPORTED_SYSCALL_MAP (open_tree);
>> + UNSUPPORTED_SYSCALL_MAP (move_mount);
>> + UNSUPPORTED_SYSCALL_MAP (fsopen);
>> + UNSUPPORTED_SYSCALL_MAP (fsconfig);
>> + UNSUPPORTED_SYSCALL_MAP (fsmount);
>> + UNSUPPORTED_SYSCALL_MAP (fspick);
>> + UNSUPPORTED_SYSCALL_MAP (pidfd_open);
>> + UNSUPPORTED_SYSCALL_MAP (clone3);
>> + UNSUPPORTED_SYSCALL_MAP (close_range);
>> + UNSUPPORTED_SYSCALL_MAP (openat2);
>> + UNSUPPORTED_SYSCALL_MAP (pidfd_getfd);
>> + UNSUPPORTED_SYSCALL_MAP (faccessat2);
>> + UNSUPPORTED_SYSCALL_MAP (process_madvise);
>> + UNSUPPORTED_SYSCALL_MAP (epoll_pwait2);
>> + UNSUPPORTED_SYSCALL_MAP (mount_setattr);
>> + UNSUPPORTED_SYSCALL_MAP (quotactl_fd);
>> + UNSUPPORTED_SYSCALL_MAP (landlock_create_ruleset);
>> + UNSUPPORTED_SYSCALL_MAP (landlock_add_rule);
>> + UNSUPPORTED_SYSCALL_MAP (landlock_restrict_self);
>> + UNSUPPORTED_SYSCALL_MAP (process_mrelease);
>> + UNSUPPORTED_SYSCALL_MAP (futex_waitv);
>> + UNSUPPORTED_SYSCALL_MAP (set_mempolicy_home_node);
>> + UNSUPPORTED_SYSCALL_MAP (cachestat);
>> + UNSUPPORTED_SYSCALL_MAP (fchmodat2);
>> + UNSUPPORTED_SYSCALL_MAP (map_shadow_stack);
>> + UNSUPPORTED_SYSCALL_MAP (futex_wake);
>> + UNSUPPORTED_SYSCALL_MAP (futex_wait);
>> + UNSUPPORTED_SYSCALL_MAP (futex_requeue);
>> + UNSUPPORTED_SYSCALL_MAP (statmount);
>> + UNSUPPORTED_SYSCALL_MAP (listmount);
>> + UNSUPPORTED_SYSCALL_MAP (lsm_get_self_attr);
>> + UNSUPPORTED_SYSCALL_MAP (lsm_set_self_attr);
>> + UNSUPPORTED_SYSCALL_MAP (lsm_list_modules);
>> + UNSUPPORTED_SYSCALL_MAP (mseal);
>> + UNSUPPORTED_SYSCALL_MAP (syscalls);
>> + default:
>> + return gdb_sys_no_syscall;
>> + }
> Small nit, but after this function, it would be nice if SYSCALL_MAP and
> UNSUPPORTED_SYSCALL_MAP were undefined so they aren't accidentally
> exported.
>> +}
>> +
>> +static int
>> +loongarch_record_all_but_pc_registers (struct regcache *regcache)
>> +{
>> +
>> + /* Record General purpose Registers. */
>> + for (int i = 0; i < 32; ++i)
>> + if (record_full_arch_list_add_reg (regcache, i))
>> + return -1;
>> +
>> + /* Record orig_a0 */
>> + if (record_full_arch_list_add_reg (regcache,
>> LOONGARCH_ORIG_A0_REGNUM))
>> + return -1;
>> +
>> + /* Record badvaddr */
>> + if (record_full_arch_list_add_reg (regcache, LOONGARCH_BADV_REGNUM))
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +/* Handler for LoongArch architechture system call instruction
>> recording. */
>> +
>> +static int
>> +loongarch_linux_syscall_record (struct regcache *regcache,
>> + unsigned long syscall_number)
>> +{
>> + int ret = 0;
>> + enum gdb_syscall syscall_gdb;
>> +
>> + syscall_gdb =
>> + loongarch_canonicalize_syscall ((enum loongarch_syscall)
>> syscall_number);
>> +
>> + if (syscall_gdb < 0)
>> + {
>> + gdb_printf (gdb_stderr,
>> + _("Process record and replay target doesn't "
>> + "support syscall number %s\n"),
>> + plongest (syscall_number));
>> + }
>> +
>> + if (syscall_gdb == gdb_sys_sigreturn || syscall_gdb ==
>> gdb_sys_rt_sigreturn)
>> + return loongarch_record_all_but_pc_registers (regcache);
>> +
>> + ret = record_linux_system_call (syscall_gdb, regcache,
>> + &loongarch_linux_record_tdep);
>> +
>> + if (ret != 0)
>> + return ret;
>> +
>> + /* Record the return value of the system call. */
>> + if (record_full_arch_list_add_reg (regcache, LOONGARCH_A0_REGNUM))
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +/* Initialize the loongarch_linux_record_tdep. These values are the size
>> + of the type that will be used in a system call. They are obtained
>> from
>> + Linux Kernel source. */
>> +
>> +static void
>> +Init_loongarch_linux_record_tdep (struct gdbarch *gdbarch)
> Capital I here should be lower case.
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-11-19 13:22 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-11-13 9:53 [PATCH 0/4] gdb: LoongArch: Add process record/replay and reverse debugging support Hui Li
2024-11-13 9:53 ` [PATCH 1/4] gdb: LoongArch: Add instruction definition for process record Hui Li
2024-11-13 12:03 ` Guinevere Larsen
2024-11-19 13:07 ` Hui Li
2024-11-13 9:53 ` [PATCH 2/4] gdb: LoongArch: Add basic process record/replay support Hui Li
2024-11-13 12:41 ` Guinevere Larsen
2024-11-14 17:23 ` Guinevere Larsen
2024-11-19 13:20 ` Hui Li
2024-11-13 9:53 ` [PATCH 3/4] gdb: LoongArch: Add system call support for process record/replay Hui Li
2024-11-13 13:01 ` Guinevere Larsen
2024-11-19 13:22 ` Hui Li
2024-11-13 9:53 ` [PATCH 4/4] gdb: Add LoongArch process record/replay support in NEWS and doc Hui Li
2024-11-13 15:01 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).