diff --git a/add-loongarch-support-not-upstream-makefile.patch b/add-loongarch-support-not-upstream-makefile.patch new file mode 100644 index 0000000000000000000000000000000000000000..da337ee52255d6033971cfcfb2e13150f434cd3b --- /dev/null +++ b/add-loongarch-support-not-upstream-makefile.patch @@ -0,0 +1,57 @@ +From 9df559fef66ab738a968367c12fcf5982c89a2f7 Mon Sep 17 00:00:00 2001 +From: herengui +Date: Tue, 29 Aug 2023 09:25:34 +0800 +Subject: [PATCH 1/2] add loongarch support not upstream makefile + +Signed-off-by: herengui +--- + configure.ac | 3 +++ + sysdeps/linux-gnu/Makefile.am | 4 ++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 63fd950..205457e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -43,6 +43,7 @@ case "${host_cpu}" in + arm*|sa110) HOST_CPU="arm" ;; + aarch64_be) HOST_CPU="aarch64" ;; + cris*) HOST_CPU="cris" ;; ++ loongarch*) HOST_CPU="loongarch" ;; + mips*) HOST_CPU="mips" ;; + powerpc|powerpc64) HOST_CPU="ppc" ;; + sun4u|sparc64) HOST_CPU="sparc" ;; +@@ -216,6 +217,7 @@ if test x"$enable_libunwind" = xyes; then + powerpc) UNWIND_ARCH="ppc32" ;; + powerpc64) UNWIND_ARCH="ppc64" ;; + mips*) UNWIND_ARCH="mips" ;; ++ loongarch*) UNWIND_ARCH="loongarch" ;; + *) UNWIND_ARCH="${host_cpu}" ;; + esac + +@@ -405,6 +407,7 @@ AC_CONFIG_FILES([ + sysdeps/linux-gnu/arm/Makefile + sysdeps/linux-gnu/cris/Makefile + sysdeps/linux-gnu/ia64/Makefile ++ sysdeps/linux-gnu/loongarch/Makefile + sysdeps/linux-gnu/m68k/Makefile + sysdeps/linux-gnu/metag/Makefile + sysdeps/linux-gnu/mips/Makefile +diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am +index ec26162..7d17020 100644 +--- a/sysdeps/linux-gnu/Makefile.am ++++ b/sysdeps/linux-gnu/Makefile.am +@@ -17,8 +17,8 @@ + # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + # 02110-1301 USA + +-DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k metag mips ppc s390 \ +- sparc x86 ++DIST_SUBDIRS = aarch64 alpha arm cris ia64 loongarch m68k metag mips \ ++ ppc s390 sparc x86 + + SUBDIRS = \ + $(HOST_CPU) +-- +2.41.0 + diff --git a/add-loongarch-support-not-upstream-sysdeps.patch b/add-loongarch-support-not-upstream-sysdeps.patch new file mode 100644 index 0000000000000000000000000000000000000000..df0dc0e7dc0c863c4fc6ac40eab74af60c06fb3b --- /dev/null +++ b/add-loongarch-support-not-upstream-sysdeps.patch @@ -0,0 +1,1866 @@ +From fad8d68e73477484b0c7cee1494de6b441b30155 Mon Sep 17 00:00:00 2001 +From: herengui +Date: Tue, 29 Aug 2023 09:25:54 +0800 +Subject: [PATCH 2/2] add loongarch support not upstream loongarch deps + +Signed-off-by: herengui +--- + sysdeps/linux-gnu/loongarch/Makefile.am | 25 + + sysdeps/linux-gnu/loongarch/arch.h | 48 ++ + sysdeps/linux-gnu/loongarch/fetch.c | 770 +++++++++++++++++++++++ + sysdeps/linux-gnu/loongarch/plt.c | 58 ++ + sysdeps/linux-gnu/loongarch/ptrace.h | 23 + + sysdeps/linux-gnu/loongarch/regs.c | 61 ++ + sysdeps/linux-gnu/loongarch/signalent.h | 52 ++ + sysdeps/linux-gnu/loongarch/syscallent.h | 471 ++++++++++++++ + sysdeps/linux-gnu/loongarch/trace.c | 274 ++++++++ + 9 files changed, 1782 insertions(+) + create mode 100644 sysdeps/linux-gnu/loongarch/Makefile.am + create mode 100644 sysdeps/linux-gnu/loongarch/arch.h + create mode 100644 sysdeps/linux-gnu/loongarch/fetch.c + create mode 100644 sysdeps/linux-gnu/loongarch/plt.c + create mode 100644 sysdeps/linux-gnu/loongarch/ptrace.h + create mode 100644 sysdeps/linux-gnu/loongarch/regs.c + create mode 100644 sysdeps/linux-gnu/loongarch/signalent.h + create mode 100644 sysdeps/linux-gnu/loongarch/syscallent.h + create mode 100644 sysdeps/linux-gnu/loongarch/trace.c + +diff --git a/sysdeps/linux-gnu/loongarch/Makefile.am b/sysdeps/linux-gnu/loongarch/Makefile.am +new file mode 100644 +index 0000000..f4da7cf +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/Makefile.am +@@ -0,0 +1,25 @@ ++# This file is part of ltrace. ++# Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++# ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++# 02110-1301 USA ++ ++noinst_LTLIBRARIES = ../libcpu.la ++ ++___libcpu_la_SOURCES = fetch.c plt.c regs.c trace.c ++ ++noinst_HEADERS = arch.h ptrace.h signalent.h syscallent.h ++ ++MAINTAINERCLEANFILES = Makefile.in +diff --git a/sysdeps/linux-gnu/loongarch/arch.h b/sysdeps/linux-gnu/loongarch/arch.h +new file mode 100644 +index 0000000..52c8b2a +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/arch.h +@@ -0,0 +1,48 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#ifndef LTRACE_LOONGARCH_ARCH_H ++#define LTRACE_LOONGARCH_ARCH_H ++ ++ ++/* | 31 15 | 14 0 | ++ * | 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 | code | */ ++#define BREAKPOINT_VALUE { 0x00, 0x00, 0x2A, 0x00 } ++#define BREAKPOINT_LENGTH 4 ++#define DECR_PC_AFTER_BREAK 0 ++#define ARCH_ENDIAN_LITTLE ++ ++#define LT_ELFCLASS ELFCLASS64 ++#define LT_ELF_MACHINE EM_LOONGARCH ++ ++#define ARCH_HAVE_SIZEOF ++#define ARCH_HAVE_ALIGNOF ++#define ARCH_HAVE_ADD_PLT_ENTRY ++#define ARCH_HAVE_SW_SINGLESTEP ++#define ARCH_HAVE_FETCH_ARG ++#define ARCH_HAVE_FETCH_PACK ++ ++#define RLEN 8 ++#define ARG_GAR_START 4 ++#define ARG_GAR_END 11 ++#define ARG_FAR_START 0 ++#define ARG_FAR_END 7 ++ ++#endif /* LTRACE_LOONGARCH_ARCH_H */ +diff --git a/sysdeps/linux-gnu/loongarch/fetch.c b/sysdeps/linux-gnu/loongarch/fetch.c +new file mode 100644 +index 0000000..779e841 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/fetch.c +@@ -0,0 +1,770 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "fetch.h" ++#include "proc.h" ++#include "type.h" ++#include "value.h" ++#include "arch.h" ++#include "expr.h" ++ ++enum fetch_method { ++ FETCH_NOP, ++ FETCH_STACK, ++ FETCH_GAR, ++ FETCH_FAR, ++}; ++ ++struct small_struct_data_t { ++ char fixed_member; ++ char float_member; ++ bool first_member_is_float; ++}; ++ ++struct fetch_context { ++ struct user_pt_regs gregs; ++ struct user_fp_state fpregs; ++ unsigned int ngr; ++ unsigned int nfr; ++ arch_addr_t stack_pointer; ++ arch_addr_t retval; ++ bool in_varargs; ++}; ++ ++static int ++loongarch_read_gregs(struct process *proc, struct user_pt_regs *regs) ++{ ++ *regs = (struct user_pt_regs) {}; ++ struct iovec iovec; ++ iovec.iov_base = regs; ++ iovec.iov_len = sizeof *regs; ++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0 ++ ? -1 : 0; ++} ++ ++static int ++loongarch_read_fregs(struct process *proc, struct user_fp_state *regs) ++{ ++ *regs = (struct user_fp_state) {}; ++ struct iovec iovec; ++ iovec.iov_base = regs; ++ iovec.iov_len = sizeof *regs; ++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0 ++ ? -1 : 0; ++} ++ ++static void ++get_array_member(struct arg_type_info *info, ++ struct small_struct_data_t *small_struct) ++{ ++ long len; ++ struct arg_type_info *array_type = info->u.array_info.elt_type; ++ expr_eval_constant(info->u.array_info.length, &len); ++ switch (array_type->type) { ++ case ARGTYPE_STRUCT: ++ break; ++ case ARGTYPE_FLOAT: ++ case ARGTYPE_DOUBLE: ++ small_struct->float_member += len; ++ break; ++ default: ++ if (small_struct->float_member > 0 ++ && small_struct->fixed_member == 0) ++ small_struct->first_member_is_float = true; ++ small_struct->fixed_member += len; ++ break; ++ } ++} ++ ++static void ++get_struct_member(struct arg_type_info *info, ++ struct small_struct_data_t *small_struct) ++{ ++ for (size_t i = 0; i < type_struct_size(info); i++) { ++ struct arg_type_info *field = type_struct_get(info, i); ++ assert(field != NULL); ++ switch (field->type) { ++ case ARGTYPE_STRUCT: ++ get_struct_member(field, small_struct); ++ break; ++ case ARGTYPE_ARRAY: ++ get_array_member(field, small_struct); ++ break; ++ case ARGTYPE_FLOAT: ++ case ARGTYPE_DOUBLE: ++ small_struct->float_member++; ++ break; ++ default: ++ if (small_struct->float_member > 0 ++ && small_struct->fixed_member == 0) ++ small_struct->first_member_is_float = true; ++ small_struct->fixed_member++; ++ break; ++ } ++ } ++} ++ ++static int ++context_init(struct fetch_context *context, struct process *proc, ++ struct arg_type_info *ret_info) ++{ ++ if (loongarch_read_gregs(proc, &context->gregs) < 0 ++ || loongarch_read_fregs(proc, &context->fpregs) < 0) ++ return -1; ++ ++ context->ngr = ARG_GAR_START; ++ context->nfr = ARG_FAR_START; ++ context->stack_pointer = (arch_addr_t)context->gregs.regs[3]; ++ context->retval = 0; ++ context->in_varargs = false; ++ ++ return 0; ++} ++ ++static int ++fetch_gar(struct fetch_context *context, struct value *value, ++ size_t offset, size_t len) ++{ ++ unsigned char *buf = value_get_raw_data(value); ++ unsigned long u = context->gregs.regs[context->ngr++]; ++ memcpy(buf + offset, &u, len); ++ ++ return 0; ++} ++ ++static int ++fetch_far(struct fetch_context *context, struct value *value, ++ size_t offset, size_t len) ++{ ++ unsigned char *buf = value_get_raw_data(value); ++ uint64_t u = context->fpregs.fpr[context->nfr++]; ++ memcpy(buf + offset, &u, len); ++ ++ return 0; ++} ++ ++static int ++fetch_stack(struct fetch_context *context, struct value *value, ++ size_t align, size_t sz) ++{ ++ if (align < 8) ++ align = 8; ++ size_t amount = ((sz + align - 1) / align) * align; ++ uintptr_t sp = (uintptr_t) context->stack_pointer; ++ sp = ((sp + align - 1) / align) * align; ++ ++ value_in_inferior(value, (arch_addr_t) sp); ++ ++ sp += amount; ++ context->stack_pointer = (arch_addr_t) sp; ++ ++ return 0; ++} ++ ++static void ++classify_struct_argument(struct fetch_context const *context, ++ struct small_struct_data_t small_struct, ++ enum fetch_method methods[], size_t sz) ++{ ++ /* "big" structs are dealt with in arch_fetch_arg_init(). */ ++ if (RLEN < sz && sz <= 2 * RLEN) { ++ /* Only fixed-point members, the argument is passed in a ++ * pair of available GAR,with the low-order bits in the ++ * lower-numbered GAR and the high-order bits in the ++ * higher-numbered GAR. If only one GAR is available, the ++ * low-order bits are in the GAR and the high-order bits ++ * are on the stack, and passed on the stack if no GAR is ++ * available. */ ++ if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 0) { ++ if (context->ngr < ARG_GAR_END) ++ methods[0] = methods[1] = FETCH_GAR; ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } else if (small_struct.fixed_member == 0 ++ && small_struct.float_member > 0) { ++ /* The structure has one long double member or one ++ * double member and two adjacent float members or ++ * 3-4 float members. The argument is passed in a ++ * pair of available GAR, with the low-order bits ++ * in the lower-numbered GAR and the high-order bits ++ * in the higher-numbered GAR. If only one GAR is ++ * available, the low-order bits are in the GAR and ++ * the high-order bits are on the stack, and passed ++ * on the stack if no GAR is available. */ ++ if (small_struct.float_member > 2) { ++ if (context->ngr < ARG_GAR_END) ++ methods[0] = methods[1] = FETCH_GAR; ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } ++ if (small_struct.float_member == 1) { ++ if (context->ngr < ARG_GAR_END) ++ methods[0] = methods[1] = FETCH_GAR; ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } else if (small_struct.float_member == 2) { ++ /* The structure with two double members is ++ * passed in a pair of available FARs. If no a ++ * pair of available FARs, it’s passed in GARs. ++ * If only one GAR is available, the low-order ++ * bits are in the GAR and the high-order bits ++ * are on the stack, and passed on the stack if ++ * no GAR available, structure with one double ++ * member and one float member is same. */ ++ if (context->nfr < ARG_FAR_END ++ && !context->in_varargs) { ++ methods[0] = methods[1] = FETCH_FAR; ++ } else { ++ if (context->ngr < ARG_GAR_END) ++ methods[0] = methods[1] = FETCH_GAR; ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } ++ } ++ } else if (small_struct.fixed_member > 0 ++ && small_struct.float_member > 0) { ++ /* The structure has one floating-point member and ++ * one fixed-point member. If one FAR and one GAR ++ * are available, the floating-point member of the ++ * structure is passed in the FAR, and the integer ++ * member of the structure is passed in the GAR; ++ * If no floating-point registers but two GARs are ++ * available, it’s passed in the two GARs; If only ++ * one GAR is available, the low-order bits are in ++ * the GAR and the high-order bits are on the stack; ++ * it’s passed on the stack if no GAR is available. */ ++ if (small_struct.fixed_member == 1 ++ && small_struct.float_member == 1) { ++ if (context->nfr <= ARG_FAR_END ++ && context->nfr <= ARG_FAR_END ++ && !context->in_varargs) { ++ if (small_struct.first_member_is_float) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_GAR; ++ } else { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_FAR; ++ } ++ } else { ++ if (context->ngr < ARG_GAR_END) ++ methods[0] = methods[1] = FETCH_GAR; ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } ++ } else { ++ /* Others, the argument is passed in a pair of ++ * available GAR, with the low-order bits in the ++ * lower-numbered GAR and the high-order bits in ++ * the higher-numbered GAR. If only one GAR is ++ * available, the low-order bits are in the GAR ++ * and the high-order bits are on the stack, and ++ * passed on the stack if no GAR is available. */ ++ if (context->ngr < ARG_GAR_END) { ++ methods[0] = methods[1] = FETCH_GAR; ++ } ++ else if (context->ngr == ARG_GAR_END) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_STACK; ++ } ++ else ++ methods[0] = methods[1] = FETCH_STACK; ++ } ++ } ++ } else if (sz <= RLEN) { ++ /* The structure has only fixed-point members. If there ++ * is an available GAR, the structure is passed through ++ * the GAR by value passing; If no GAR is available, ++ * it’s passed on the stack. */ ++ if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 0) { ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } else if (small_struct.fixed_member == 0 ++ && small_struct.float_member > 0) { ++ /* One floating-point member. The argument is passed ++ * in a FAR; If no FAR is available, the value is ++ * passed in a GAR; if no GAR is available, the value ++ * is passed on the stack. */ ++ if (small_struct.float_member == 1) { ++ if (context->nfr <= ARG_FAR_END ++ && !context->in_varargs) { ++ methods[0] = FETCH_FAR; ++ } else { ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } ++ } else if (small_struct.float_member == 2) { ++ /* Two floating-point members. argument is ++ * passed in a pair of available FAR, with ++ * the low-order float member bits in the ++ * lower-numbered FAR and the high-order ++ * float member bits in the higher-numbered ++ * FAR. If the number of available FAR is ++ * less than 2, it’s passed in a GAR, and ++ * passed on stack if no GAR available. */ ++ if (context->nfr < ARG_FAR_END ++ && !context->in_varargs) { ++ methods[0] = methods[1] = FETCH_FAR; ++ } else { ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } ++ } ++ } else if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 1) { ++ /* Multiple fixed-point members. If there are ++ * available GAR, the structure passed in a GAR, ++ * and passed on the stack if no GAR is available. */ ++ if (small_struct.fixed_member > 1) { ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } else if (small_struct.fixed_member == 1) { ++ /* Only one fixed-point member. If one FAR ++ * and one GAR are available, floating-point ++ * member of the structure is passed in FAR, ++ * and the integer member is passed in GAR; ++ * If no floating-point register but one GAR ++ * is available, it’s passed in GAR; If no ++ * GAR is available, it’s passed on stack. */ ++ if (context->nfr <= ARG_FAR_END ++ && context->nfr <= ARG_FAR_END ++ && !context->in_varargs) { ++ if (small_struct.first_member_is_float) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_GAR; ++ } else { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_GAR; ++ } ++ } else { ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } ++ } ++ } ++ } ++} ++ ++static int ++classify_argument(struct fetch_context const *context, ++ struct process *proc, struct arg_type_info *info, ++ enum fetch_method methods[]) ++{ ++ struct small_struct_data_t small_struct = {0, 0, false}; ++ size_t sz = type_sizeof(proc, info); ++ if (sz == (size_t) -1) ++ return -1; ++ ++ switch (info->type) { ++ case ARGTYPE_VOID: ++ return -1; ++ ++ case ARGTYPE_STRUCT: ++ get_struct_member (info, &small_struct); ++ classify_struct_argument(context, small_struct, methods, sz); ++ return 0; ++ case ARGTYPE_POINTER: ++ case ARGTYPE_ARRAY: ++ case ARGTYPE_INT: ++ case ARGTYPE_UINT: ++ case ARGTYPE_LONG: ++ case ARGTYPE_ULONG: ++ case ARGTYPE_CHAR: ++ case ARGTYPE_SHORT: ++ case ARGTYPE_USHORT: ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ return 0; ++ case ARGTYPE_FLOAT: ++ case ARGTYPE_DOUBLE: ++ if (context->nfr <= ARG_FAR_END && !context->in_varargs) ++ methods[0] = FETCH_FAR; ++ else if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ return 0; ++ } ++ ++ assert(!"Failed to classify argument."); ++ abort(); ++} ++ ++ ++static int ++classify_return_value(struct fetch_context const *context, ++ struct process *proc, struct arg_type_info *info, ++ enum fetch_method methods[]) ++{ ++ struct small_struct_data_t small_struct = {0, 0, false}; ++ size_t sz = type_sizeof(proc, info); ++ if (sz == (size_t) -1) ++ return -1; ++ ++ switch (info->type) { ++ case ARGTYPE_VOID: ++ return 0; ++ case ARGTYPE_STRUCT: ++ get_struct_member (info, &small_struct); ++ /* sz <= RLEN */ ++ if (sz <= RLEN) { ++ /* The structure has only fixed-point members. ++ * passed on $v0. */ ++ if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 0) ++ methods[0] = FETCH_GAR; ++ /* The structure has only floating-point members. */ ++ else if (small_struct.fixed_member == 0 ++ && small_struct.float_member > 0) { ++ /* One floating-point member. passed on $fv0 */ ++ if (small_struct.float_member == 1) ++ methods[0] = FETCH_FAR; ++ /* Two floating-point members. passed on $fv0 ++ * and $fv1 */ ++ else if (small_struct.float_member == 2) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_FAR; ++ } ++ } ++ /* The structure has both fixed-point and floating ++ * point members */ ++ else if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 1) { ++ /* Multiple fixed-point members. passed on ++ * $v0. */ ++ if (small_struct.fixed_member > 1) ++ methods[0] = FETCH_GAR; ++ /* Only one fixed-point member. float-point ++ * member is passed on $fv0, fixed-point member ++ * is passed on $v0. */ ++ else if (small_struct.fixed_member == 1) { ++ if (small_struct.first_member_is_float) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_GAR; ++ } else { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_FAR; ++ } ++ } ++ } ++ } ++ /* RLEN < sz && sz <= 2 * RLEN */ ++ else if (RLEN < sz && sz <= 2 * RLEN) { ++ /* Only fixed-point members, passed on $v0 and $v1 */ ++ if (small_struct.fixed_member > 0 ++ && small_struct.float_member == 0) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_GAR; ++ } ++ /* Only floating-point members. */ ++ else if (small_struct.fixed_member == 0 ++ && small_struct.float_member > 0) { ++ /* The structure has one long double member ++ * or one double member and two adjacent ++ * float members or 3-4 float members. passed ++ * on $v0 and $v1. */ ++ if (small_struct.float_member == 1 ++ || small_struct.float_member > 2) { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_GAR; ++ } ++ /* The structure two double member, passed on ++ * $fv0 and $fv1. */ ++ if (small_struct.float_member == 2) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_FAR; ++ } ++ } ++ /* Both fixed-point and floating-point members. */ ++ else if (small_struct.fixed_member > 0 ++ && small_struct.float_member > 0) { ++ /* The structure has one floating-point member ++ * and one fixed-point member. float-point ++ * member is passed on $fv0, fixed-point member ++ * is passed on $v0.*/ ++ if (small_struct.fixed_member == 1 ++ && small_struct.float_member == 1) { ++ if (small_struct.first_member_is_float) { ++ methods[0] = FETCH_FAR; ++ methods[1] = FETCH_GAR; ++ } else { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_FAR; ++ } ++ } ++ /* Others, passed on $v0 and $v1. */ ++ else { ++ methods[0] = FETCH_GAR; ++ methods[1] = FETCH_GAR; ++ } ++ } ++ } ++ return 0; ++ case ARGTYPE_POINTER: ++ case ARGTYPE_ARRAY: ++ case ARGTYPE_INT: ++ case ARGTYPE_UINT: ++ case ARGTYPE_LONG: ++ case ARGTYPE_ULONG: ++ case ARGTYPE_CHAR: ++ case ARGTYPE_SHORT: ++ case ARGTYPE_USHORT: ++ methods[0] = FETCH_GAR; ++ return 0; ++ case ARGTYPE_FLOAT: ++ case ARGTYPE_DOUBLE: ++ methods[0] = FETCH_FAR; ++ return 0; ++ } ++ ++ assert(!"Failed to classify retval."); ++ abort(); ++} ++ ++static int ++fetch_argument(struct fetch_context *context, ++ struct process *proc, struct arg_type_info *info, ++ struct value *value, enum fetch_method method, ++ size_t offset, size_t len) ++{ ++ switch (method) { ++ case FETCH_NOP: ++ return 0; ++ ++ case FETCH_STACK: ++ return fetch_stack(context, value, RLEN, RLEN); ++ ++ case FETCH_GAR: ++ return fetch_gar(context, value, offset, len); ++ ++ case FETCH_FAR: ++ return fetch_far(context, value, offset, len); ++ ++ } ++ ++ assert(!"Don't know how to fetch argument."); ++ abort(); ++} ++ ++static int ++fetch_return_value(struct fetch_context *context, struct process *proc, ++ struct arg_type_info *info, struct value *value, ++ enum fetch_method method, size_t offset, size_t len) ++{ ++ ++ switch (method) { ++ case FETCH_NOP: ++ return 0; ++ case FETCH_STACK: ++ return 0; ++ ++ case FETCH_GAR: ++ return fetch_gar(context, value, offset, len); ++ ++ case FETCH_FAR: ++ return fetch_far(context, value, offset, len); ++ ++ } ++ ++ assert(!"Don't know how to fetch retval."); ++ abort(); ++} ++ ++struct fetch_context * ++arch_fetch_arg_clone(struct process *proc, struct fetch_context *context) ++{ ++ struct fetch_context *ret = malloc(sizeof(*ret)); ++ ++ if (ret == NULL) ++ return NULL; ++ return memcpy(ret, context, sizeof(*ret)); ++} ++ ++struct fetch_context * ++arch_fetch_arg_init(enum tof type, struct process *proc, ++ struct arg_type_info *ret_info) ++{ ++ struct fetch_context *context = malloc(sizeof *context); ++ if (context == NULL || context_init(context, proc, ret_info) < 0) { ++fail: ++ free(context); ++ return NULL; ++ } ++ ++ size_t sz = type_sizeof(proc, ret_info); ++ if (sz == (size_t) -1) ++ goto fail; ++ ++ if (sz > 2 * RLEN) { ++ /* The reference of the return value is stored in GAR a0 ++ * if the size of return value is larger than 2*GRLEN bits */ ++ context->retval = (arch_addr_t) context->gregs.regs[context->ngr++]; ++ } ++ ++ return context; ++} ++ ++int ++arch_fetch_arg_next(struct fetch_context *context, enum tof type, ++ struct process *proc, struct arg_type_info *info, ++ struct value *value) ++{ ++ enum fetch_method methods[2] = {FETCH_NOP, FETCH_NOP}; ++ size_t len = RLEN; ++ size_t sz = type_sizeof(proc, info); ++ if (sz == (size_t) -1) ++ return -1; ++ if (sz > 2 * RLEN) { ++ sz = 8; ++ value_pass_by_reference(value); ++ if (context->ngr <= ARG_GAR_END) ++ methods[0] = FETCH_GAR; ++ else ++ methods[0] = FETCH_STACK; ++ } else { ++ if (classify_argument(context, proc, info, methods) != 0) ++ return -1; ++ } ++ ++ if (value_reserve(value, sz) == NULL) ++ return -1; ++ ++ if (methods[1] == FETCH_NOP) { ++ fetch_argument(context, proc, info, value, methods[0], 0, RLEN); ++ } else { ++ if (sz <= RLEN) ++ len = RLEN / 2; ++ ++ fetch_argument(context, proc, info, value, methods[0], 0, len); ++ fetch_argument(context, proc, info, value, methods[1], len, len); ++ } ++ ++ return 0; ++} ++ ++int ++arch_fetch_retval(struct fetch_context *context, enum tof type, ++ struct process *proc, struct arg_type_info *info, ++ struct value *value) ++{ ++ size_t len = RLEN; ++ size_t sz = type_sizeof(proc, info); ++ if (sz == (size_t) -1) ++ return -1; ++ ++ if (type == LT_TOF_FUNCTIONR) { ++ enum fetch_method methods[2] = {FETCH_NOP, FETCH_NOP}; ++ if (context->retval != 0) { ++ /* return value is larger than 2*GRLEN ++ * was extracted when in fetch init. */ ++ value_in_inferior(value, context->retval); ++ return 0; ++ } ++ ++ if (context_init(context, proc, info) < 0) ++ return -1; ++ ++ if (classify_return_value(context, proc, info, methods) != 0) ++ return -1; ++ ++ if (value_reserve(value, sz) == NULL) ++ return -1; ++ ++ if (methods[1] == FETCH_NOP) { ++ fetch_return_value(context, proc, info, value, ++ methods[0], 0, RLEN); ++ } else { ++ if (sz <= RLEN) ++ len = RLEN / 2; ++ ++ fetch_return_value(context, proc, info, value, ++ methods[0], 0, len); ++ fetch_return_value(context, proc, info, value, ++ methods[1], len, len); ++ } ++ ++ } ++ /* SYSCALLR,return value in GAR a0 */ ++ else if (type == LT_TOF_SYSCALLR) ++ value_in_inferior(value, (arch_addr_t) context->gregs.regs[4]); ++ ++ return 0; ++} ++ ++void ++arch_fetch_arg_done(struct fetch_context *context) ++{ ++ if (context != NULL) ++ free(context); ++} ++ ++int ++arch_fetch_param_pack_start(struct fetch_context *context, ++ enum param_pack_flavor ppflavor) ++{ ++ if (ppflavor == PARAM_PACK_VARARGS) ++ context->in_varargs = true; ++ return 0; ++} ++ ++void ++arch_fetch_param_pack_end(struct fetch_context *context) ++{ ++ context->in_varargs = false; ++} +diff --git a/sysdeps/linux-gnu/loongarch/plt.c b/sysdeps/linux-gnu/loongarch/plt.c +new file mode 100644 +index 0000000..4dd9235 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/plt.c +@@ -0,0 +1,58 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include "backend.h" ++#include "proc.h" ++#include "library.h" ++#include "ltrace-elf.h" ++#include "trace.h" ++ ++arch_addr_t ++sym2addr(struct process *proc, struct library_symbol *sym) ++{ ++ return sym->enter_addr; ++} ++ ++GElf_Addr ++arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela) ++{ ++ return lte->plt_addr + 32 + ndx * 16; ++} ++ ++ ++enum plt_status ++arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte, ++ const char *a_name, GElf_Rela *rela, size_t ndx, ++ struct library_symbol **ret) ++{ ++#ifdef R_LARCH_IRELATIVE ++ bool irelative = GELF_R_TYPE(rela->r_info) == R_LARCH_IRELATIVE; ++#else ++ bool irelative = false; ++#endif ++ ++ if (irelative) ++ return linux_elf_add_plt_entry_irelative(proc, lte, rela, ++ ndx, ret); ++ ++ return PLT_DEFAULT; ++} +diff --git a/sysdeps/linux-gnu/loongarch/ptrace.h b/sysdeps/linux-gnu/loongarch/ptrace.h +new file mode 100644 +index 0000000..3685186 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/ptrace.h +@@ -0,0 +1,23 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include +diff --git a/sysdeps/linux-gnu/loongarch/regs.c b/sysdeps/linux-gnu/loongarch/regs.c +new file mode 100644 +index 0000000..304b2b4 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/regs.c +@@ -0,0 +1,61 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include "proc.h" ++#include "common.h" ++#include "backend.h" ++ ++#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) ++# define PTRACE_PEEKUSER PTRACE_PEEKUSR ++#endif ++ ++#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) ++# define PTRACE_POKEUSER PTRACE_POKEUSR ++#endif ++ ++void * ++get_instruction_pointer(struct process *proc) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PC, 0); ++} ++ ++void ++set_instruction_pointer(struct process *proc, void *addr) ++{ ++ ptrace(PTRACE_POKEUSER, proc->pid, PC, addr); ++} ++ ++void * ++get_stack_pointer(struct process *proc) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, GPR_BASE + 3, 0); ++} ++ ++void * ++get_return_addr(struct process *proc, void *stack_pointer) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, GPR_BASE + 1, 0); ++} +diff --git a/sysdeps/linux-gnu/loongarch/signalent.h b/sysdeps/linux-gnu/loongarch/signalent.h +new file mode 100644 +index 0000000..4c0a466 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/signalent.h +@@ -0,0 +1,52 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++ "SIG_0", /* 0 */ ++ "SIGHUP", /* 1 */ ++ "SIGINT", /* 2 */ ++ "SIGQUIT", /* 3 */ ++ "SIGILL", /* 4 */ ++ "SIGTRAP", /* 5 */ ++ "SIGABRT", /* 6 */ ++ "SIGBUS", /* 7 */ ++ "SIGFPE", /* 8 */ ++ "SIGKILL", /* 9 */ ++ "SIGUSR1", /* 10 */ ++ "SIGSEGV", /* 11 */ ++ "SIGUSR2", /* 12 */ ++ "SIGPIPE", /* 13 */ ++ "SIGALRM", /* 14 */ ++ "SIGTERM", /* 15 */ ++ "SIGSTKFLT", /* 16 */ ++ "SIGCHLD", /* 17 */ ++ "SIGCONT", /* 18 */ ++ "SIGSTOP", /* 19 */ ++ "SIGTSTP", /* 20 */ ++ "SIGTTIN", /* 21 */ ++ "SIGTTOU", /* 22 */ ++ "SIGURG", /* 23 */ ++ "SIGXCPU", /* 24 */ ++ "SIGXFSZ", /* 25 */ ++ "SIGVTALRM", /* 26 */ ++ "SIGPROF", /* 27 */ ++ "SIGWINCH", /* 28 */ ++ "SIGIO", /* 29 */ ++ "SIGPWR", /* 30 */ ++ "SIGSYS", /* 31 */ +diff --git a/sysdeps/linux-gnu/loongarch/syscallent.h b/sysdeps/linux-gnu/loongarch/syscallent.h +new file mode 100644 +index 0000000..4d50cad +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/syscallent.h +@@ -0,0 +1,471 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++ "io_setup", /* 0 */ ++ "io_destroy", /* 1 */ ++ "io_submit", /* 2 */ ++ "io_cancel", /* 3 */ ++ "io_getevents", /* 4 */ ++ "setxattr", /* 5 */ ++ "lsetxattr", /* 6 */ ++ "fsetxattr", /* 7 */ ++ "getxattr", /* 8 */ ++ "lgetxattr", /* 9 */ ++ "fgetxattr", /* 10 */ ++ "listxattr", /* 11 */ ++ "llistxattr", /* 12 */ ++ "flistxattr", /* 13 */ ++ "removexattr", /* 14 */ ++ "lremovexattr", /* 15 */ ++ "fremovexattr", /* 16 */ ++ "getcwd", /* 17 */ ++ "lookup_dcookie", /* 18 */ ++ "eventfd2", /* 19 */ ++ "epoll_create1", /* 20 */ ++ "epoll_ctl", /* 21 */ ++ "epoll_pwait", /* 22 */ ++ "dup", /* 23 */ ++ "dup3", /* 24 */ ++ "fcntl", /* 25 */ ++ "inotify_init1", /* 26 */ ++ "inotify_add_watch", /* 27 */ ++ "inotify_rm_watch", /* 28 */ ++ "ioctl", /* 29 */ ++ "ioprio_set", /* 30 */ ++ "ioprio_get", /* 31 */ ++ "flock", /* 32 */ ++ "mknodat", /* 33 */ ++ "mkdirat", /* 34 */ ++ "unlinkat", /* 35 */ ++ "symlinkat", /* 36 */ ++ "linkat", /* 37 */ ++ "renameat", /* 38 */ ++ "umount2", /* 39 */ ++ "mount", /* 40 */ ++ "pivot_root", /* 41 */ ++ "nfsservctl", /* 42 */ ++ "statfs", /* 43 */ ++ "fstatfs", /* 44 */ ++ "truncate", /* 45 */ ++ "ftruncate", /* 46 */ ++ "fallocate", /* 47 */ ++ "faccessat", /* 48 */ ++ "chdir", /* 49 */ ++ "fchdir", /* 50 */ ++ "chroot", /* 51 */ ++ "fchmod", /* 52 */ ++ "fchmodat", /* 53 */ ++ "fchownat", /* 54 */ ++ "fchown", /* 55 */ ++ "openat", /* 56 */ ++ "close", /* 57 */ ++ "vhangup", /* 58 */ ++ "pipe2", /* 59 */ ++ "quotactl", /* 60 */ ++ "getdents64", /* 61 */ ++ "lseek", /* 62 */ ++ "read", /* 63 */ ++ "write", /* 64 */ ++ "readv", /* 65 */ ++ "writev", /* 66 */ ++ "pread64", /* 67 */ ++ "pwrite64", /* 68 */ ++ "preadv", /* 69 */ ++ "pwritev", /* 70 */ ++ "sendfile64", /* 71 */ ++ "pselect6", /* 72 */ ++ "ppoll", /* 73 */ ++ "signalfd4", /* 74 */ ++ "vmsplice", /* 75 */ ++ "splice", /* 76 */ ++ "tee", /* 77 */ ++ "readlinkat", /* 78 */ ++ "79", /* 79 */ ++ "80", /* 80 */ ++ "sync", /* 81 */ ++ "fsync", /* 82 */ ++ "fdatasync", /* 83 */ ++ "sync_file_range", /* 84 */ ++ "timerfd_create", /* 85 */ ++ "timerfd_settime", /* 86 */ ++ "timerfd_gettime", /* 87 */ ++ "utimensat", /* 88 */ ++ "acct", /* 89 */ ++ "capget", /* 90 */ ++ "capset", /* 91 */ ++ "personality", /* 92 */ ++ "exit", /* 93 */ ++ "exit_group", /* 94 */ ++ "waitid", /* 95 */ ++ "set_tid_address", /* 96 */ ++ "unshare", /* 97 */ ++ "futex", /* 98 */ ++ "set_robust_list", /* 99 */ ++ "get_robust_list", /* 100 */ ++ "nanosleep", /* 101 */ ++ "getitimer", /* 102 */ ++ "setitimer", /* 103 */ ++ "kexec_load", /* 104 */ ++ "init_module", /* 105 */ ++ "delete_module", /* 106 */ ++ "timer_create", /* 107 */ ++ "timer_gettime", /* 108 */ ++ "timer_getoverrun", /* 109 */ ++ "timer_settime", /* 110 */ ++ "timer_delete", /* 111 */ ++ "clock_settime", /* 112 */ ++ "clock_gettime", /* 113 */ ++ "clock_getres", /* 114 */ ++ "clock_nanosleep", /* 115 */ ++ "syslog", /* 116 */ ++ "ptrace", /* 117 */ ++ "sched_setparam", /* 118 */ ++ "sched_setscheduler", /* 119 */ ++ "sched_getscheduler", /* 120 */ ++ "sched_getparam", /* 121 */ ++ "sched_setaffinity", /* 122 */ ++ "sched_getaffinity", /* 123 */ ++ "sched_yield", /* 124 */ ++ "sched_get_priority_max", /* 125 */ ++ "sched_get_priority_min", /* 126 */ ++ "sched_rr_get_interval", /* 127 */ ++ "restart_syscall", /* 128 */ ++ "kill", /* 129 */ ++ "tkill", /* 130 */ ++ "tgkill", /* 131 */ ++ "sigaltstack", /* 132 */ ++ "rt_sigsuspend", /* 133 */ ++ "rt_sigaction", /* 134 */ ++ "rt_sigprocmask", /* 135 */ ++ "rt_sigpending", /* 136 */ ++ "rt_sigtimedwait", /* 137 */ ++ "rt_sigqueueinfo", /* 138 */ ++ "rt_sigreturn", /* 139 */ ++ "setpriority", /* 140 */ ++ "getpriority", /* 141 */ ++ "reboot", /* 142 */ ++ "setregid", /* 143 */ ++ "setgid", /* 144 */ ++ "setreuid", /* 145 */ ++ "setuid", /* 146 */ ++ "setresuid", /* 147 */ ++ "getresuid", /* 148 */ ++ "setresgid", /* 149 */ ++ "getresgid", /* 150 */ ++ "setfsuid", /* 151 */ ++ "setfsgid", /* 152 */ ++ "times", /* 153 */ ++ "setpgid", /* 154 */ ++ "getpgid", /* 155 */ ++ "getsid", /* 156 */ ++ "setsid", /* 157 */ ++ "getgroups", /* 158 */ ++ "setgroups", /* 159 */ ++ "uname", /* 160 */ ++ "sethostname", /* 161 */ ++ "setdomainname", /* 162 */ ++ "getrlimit", /* 163 */ ++ "setrlimit", /* 164 */ ++ "getrusage", /* 165 */ ++ "umask", /* 166 */ ++ "prctl", /* 167 */ ++ "getcpu", /* 168 */ ++ "gettimeofday", /* 169 */ ++ "settimeofday", /* 170 */ ++ "adjtimex", /* 171 */ ++ "getpid", /* 172 */ ++ "getppid", /* 173 */ ++ "getuid", /* 174 */ ++ "geteuid", /* 175 */ ++ "getgid", /* 176 */ ++ "getegid", /* 177 */ ++ "gettid", /* 178 */ ++ "sysinfo", /* 179 */ ++ "mq_open", /* 180 */ ++ "mq_unlink", /* 181 */ ++ "mq_timedsend", /* 182 */ ++ "mq_timedreceive", /* 183 */ ++ "mq_notify", /* 184 */ ++ "mq_getsetattr", /* 185 */ ++ "msgget", /* 186 */ ++ "msgctl", /* 187 */ ++ "msgrcv", /* 188 */ ++ "msgsnd", /* 189 */ ++ "semget", /* 190 */ ++ "semctl", /* 191 */ ++ "semtimedop", /* 192 */ ++ "semop", /* 193 */ ++ "shmget", /* 194 */ ++ "shmctl", /* 195 */ ++ "shmat", /* 196 */ ++ "shmdt", /* 197 */ ++ "socket", /* 198 */ ++ "socketpair", /* 199 */ ++ "bind", /* 200 */ ++ "listen", /* 201 */ ++ "accept", /* 202 */ ++ "connect", /* 203 */ ++ "getsockname", /* 204 */ ++ "getpeername", /* 205 */ ++ "sendto", /* 206 */ ++ "recvfrom", /* 207 */ ++ "setsockopt", /* 208 */ ++ "getsockopt", /* 209 */ ++ "shutdown", /* 210 */ ++ "sendmsg", /* 211 */ ++ "recvmsg", /* 212 */ ++ "readahead", /* 213 */ ++ "brk", /* 214 */ ++ "munmap", /* 215 */ ++ "mremap", /* 216 */ ++ "add_key", /* 217 */ ++ "request_key", /* 218 */ ++ "keyctl", /* 219 */ ++ "clone", /* 220 */ ++ "execve", /* 221 */ ++ "mmap", /* 222 */ ++ "fadvise64_64", /* 223 */ ++ "swapon", /* 224 */ ++ "swapoff", /* 225 */ ++ "mprotect", /* 226 */ ++ "msync", /* 227 */ ++ "mlock", /* 228 */ ++ "munlock", /* 229 */ ++ "mlockall", /* 230 */ ++ "munlockall", /* 231 */ ++ "mincore", /* 232 */ ++ "madvise", /* 233 */ ++ "remap_file_pages", /* 234 */ ++ "mbind", /* 235 */ ++ "get_mempolicy", /* 236 */ ++ "set_mempolicy", /* 237 */ ++ "migrate_pages", /* 238 */ ++ "move_pages", /* 239 */ ++ "rt_tgsigqueueinfo", /* 240 */ ++ "perf_event_open", /* 241 */ ++ "accept4", /* 242 */ ++ "recvmmsg", /* 243 */ ++ "arch_specific_syscall", /* 244 */ ++ "245", /* 245 */ ++ "246", /* 246 */ ++ "247", /* 247 */ ++ "248", /* 248 */ ++ "249", /* 249 */ ++ "250", /* 250 */ ++ "251", /* 251 */ ++ "252", /* 252 */ ++ "253", /* 253 */ ++ "254", /* 254 */ ++ "255", /* 255 */ ++ "256", /* 256 */ ++ "257", /* 257 */ ++ "258", /* 258 */ ++ "259", /* 259 */ ++ "wait4", /* 260 */ ++ "prlimit64", /* 261 */ ++ "fanotify_init", /* 262 */ ++ "fanotify_mark", /* 263 */ ++ "name_to_handle_at", /* 264 */ ++ "open_by_handle_at", /* 265 */ ++ "clock_adjtime", /* 266 */ ++ "syncfs", /* 267 */ ++ "setns", /* 268 */ ++ "sendmmsg", /* 269 */ ++ "process_vm_readv", /* 270 */ ++ "process_vm_writev", /* 271 */ ++ "kcmp", /* 272 */ ++ "finit_module", /* 273 */ ++ "sched_setattr", /* 274 */ ++ "sched_getattr", /* 275 */ ++ "renameat2", /* 276 */ ++ "seccomp", /* 277 */ ++ "getrandom", /* 278 */ ++ "memfd_create", /* 279 */ ++ "bpf", /* 280 */ ++ "execveat", /* 281 */ ++ "userfaultfd", /* 282 */ ++ "membarrier", /* 283 */ ++ "mlock2", /* 284 */ ++ "copy_file_range", /* 285 */ ++ "preadv2", /* 286 */ ++ "pwritev2", /* 287 */ ++ "pkey_mprotect", /* 288 */ ++ "pkey_alloc", /* 289 */ ++ "pkey_free", /* 290 */ ++ "statx", /* 291 */ ++ "io_pgetevents", /* 292 */ ++ "rseq", /* 293 */ ++ "kexec_file_load", /* 294 */ ++ "295", /* 295 */ ++ "296", /* 296 */ ++ "297", /* 297 */ ++ "298", /* 298 */ ++ "299", /* 299 */ ++ "300", /* 300 */ ++ "301", /* 301 */ ++ "302", /* 302 */ ++ "303", /* 303 */ ++ "304", /* 304 */ ++ "305", /* 305 */ ++ "306", /* 306 */ ++ "307", /* 307 */ ++ "308", /* 308 */ ++ "309", /* 309 */ ++ "310", /* 310 */ ++ "311", /* 311 */ ++ "312", /* 312 */ ++ "313", /* 313 */ ++ "314", /* 314 */ ++ "315", /* 315 */ ++ "316", /* 316 */ ++ "317", /* 317 */ ++ "318", /* 318 */ ++ "319", /* 319 */ ++ "320", /* 320 */ ++ "321", /* 321 */ ++ "322", /* 322 */ ++ "323", /* 323 */ ++ "324", /* 324 */ ++ "325", /* 325 */ ++ "326", /* 326 */ ++ "327", /* 327 */ ++ "328", /* 328 */ ++ "329", /* 329 */ ++ "330", /* 330 */ ++ "331", /* 331 */ ++ "332", /* 332 */ ++ "333", /* 333 */ ++ "334", /* 334 */ ++ "335", /* 335 */ ++ "336", /* 336 */ ++ "337", /* 337 */ ++ "338", /* 338 */ ++ "339", /* 339 */ ++ "340", /* 340 */ ++ "341", /* 341 */ ++ "342", /* 342 */ ++ "343", /* 343 */ ++ "344", /* 344 */ ++ "345", /* 345 */ ++ "346", /* 346 */ ++ "347", /* 347 */ ++ "348", /* 348 */ ++ "349", /* 349 */ ++ "350", /* 350 */ ++ "351", /* 351 */ ++ "352", /* 352 */ ++ "353", /* 353 */ ++ "354", /* 354 */ ++ "355", /* 355 */ ++ "356", /* 356 */ ++ "357", /* 357 */ ++ "358", /* 358 */ ++ "359", /* 359 */ ++ "360", /* 360 */ ++ "361", /* 361 */ ++ "362", /* 362 */ ++ "363", /* 363 */ ++ "364", /* 364 */ ++ "365", /* 365 */ ++ "366", /* 366 */ ++ "367", /* 367 */ ++ "368", /* 368 */ ++ "369", /* 369 */ ++ "370", /* 370 */ ++ "371", /* 371 */ ++ "372", /* 372 */ ++ "373", /* 373 */ ++ "374", /* 374 */ ++ "375", /* 375 */ ++ "376", /* 376 */ ++ "377", /* 377 */ ++ "378", /* 378 */ ++ "379", /* 379 */ ++ "380", /* 380 */ ++ "381", /* 381 */ ++ "382", /* 382 */ ++ "383", /* 383 */ ++ "384", /* 384 */ ++ "385", /* 385 */ ++ "386", /* 386 */ ++ "387", /* 387 */ ++ "388", /* 388 */ ++ "389", /* 389 */ ++ "390", /* 390 */ ++ "391", /* 391 */ ++ "392", /* 392 */ ++ "393", /* 393 */ ++ "394", /* 394 */ ++ "395", /* 395 */ ++ "396", /* 396 */ ++ "397", /* 397 */ ++ "398", /* 398 */ ++ "399", /* 399 */ ++ "400", /* 400 */ ++ "401", /* 401 */ ++ "402", /* 402 */ ++ "403", /* 403 */ ++ "404", /* 404 */ ++ "405", /* 405 */ ++ "406", /* 406 */ ++ "407", /* 407 */ ++ "408", /* 408 */ ++ "409", /* 409 */ ++ "410", /* 410 */ ++ "411", /* 411 */ ++ "412", /* 412 */ ++ "413", /* 413 */ ++ "414", /* 414 */ ++ "415", /* 415 */ ++ "416", /* 416 */ ++ "417", /* 417 */ ++ "418", /* 418 */ ++ "419", /* 419 */ ++ "420", /* 420 */ ++ "421", /* 421 */ ++ "422", /* 422 */ ++ "423", /* 423 */ ++ "pidfd_send_signal", /* 424 */ ++ "io_uring_setup", /* 425 */ ++ "io_uring_enter", /* 426 */ ++ "io_uring_register", /* 427 */ ++ "open_tree", /* 428 */ ++ "move_mount", /* 429 */ ++ "fsopen", /* 430 */ ++ "fsconfig", /* 431 */ ++ "fsmount", /* 432 */ ++ "fspick", /* 433 */ ++ "pidfd_open", /* 434 */ ++ "clone3", /* 435 */ ++ "close_range", /* 436 */ ++ "openat2", /* 437 */ ++ "pidfd_getfd", /* 438 */ ++ "faccessat2", /* 439 */ ++ "process_madvise", /* 440 */ ++ "epoll_pwait2", /* 441 */ ++ "mount_setattr", /* 442 */ ++ "quotactl_fd", /* 443 */ ++ "landlock_create_ruleset", /* 444 */ ++ "landlock_add_rule", /* 445 */ ++ "landlock_restrict_self", /* 446 */ ++ "memfd_secret", /* 447 */ ++ "process_mrelease", /* 448 */ ++ "futex_waitv", /* 449 */ ++ "set_mempolicy_home_node", /* 450 */ +diff --git a/sysdeps/linux-gnu/loongarch/trace.c b/sysdeps/linux-gnu/loongarch/trace.c +new file mode 100644 +index 0000000..e0bf634 +--- /dev/null ++++ b/sysdeps/linux-gnu/loongarch/trace.c +@@ -0,0 +1,274 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited. ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "fetch.h" ++#include "backend.h" ++#include "proc.h" ++#include "type.h" ++#include "debug.h" ++ ++#define BRANCH_MASK 0xfc000000 ++#define OPCODE_JIRL 0x4c000000 ++#define OPCODE_B 0x50000000 ++#define OPCODE_BL 0x54000000 ++#define OPCODE_BEQ 0x58000000 ++#define OPCODE_BNE 0x5c000000 ++#define OPCODE_BLT 0x60000000 ++#define OPCODE_BGE 0x64000000 ++#define OPCODE_BLTU 0x68000000 ++#define OPCODE_BGEU 0x6c000000 ++#define OPCODE_BEQZ 0x40000000 ++#define OPCODE_BNEZ 0x44000000 ++ ++void ++get_arch_dep(struct process *proc) ++{ ++ ++} ++ ++/* Sign-extend the number in the bottom B bits of X to a 64-bit integer. ++ * Requires 0 < B < 64 */ ++static inline int64_t sign_extend64(uint64_t X, unsigned B) ++{ ++ assert(B > 0 && "Bit width can't be 0."); ++ assert(B <= 64 && "Bit width out of range."); ++ return (int64_t)(X << (64 - B)) >> (64 - B); ++} ++ ++/* Return the bit field(s) from the most significant bit (msbit) to the ++ * least significant bit (lsbit) of a 32-bit unsigned value. */ ++static inline uint32_t bits32(const uint32_t bits, const uint32_t msbit, ++ const uint32_t lsbit) ++{ ++ assert(msbit < 32 && lsbit <= msbit); ++ return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1); ++} ++ ++static int ++loongarch_get_next_pcs(struct process *proc, ++ arch_addr_t pc, arch_addr_t next_pcs[2]) ++{ ++ uint32_t insn; ++ uint32_t op; ++ uint32_t rj, imm; ++ int64_t rj_value, signext_imm; ++ int nr = 0; ++ ++ insn = (uint32_t)ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0); ++ op = insn & BRANCH_MASK; ++ ++ switch (op) { ++ case OPCODE_JIRL: ++ rj = bits32(insn, 9, 5); ++ rj_value = ptrace(PTRACE_PEEKUSER, proc->pid, rj, 0); ++ imm = bits32(insn, 25, 10); ++ signext_imm = sign_extend64(imm << 2, 18); ++ next_pcs[nr++] = (arch_addr_t)(rj_value + signext_imm); ++ next_pcs[nr++] = pc + 4; ++ break; ++ case OPCODE_B: ++ case OPCODE_BL: ++ imm = bits32(insn, 25, 10) + (bits32(insn, 9, 0) << 16); ++ signext_imm = sign_extend64(imm << 2, 28); ++ next_pcs[nr++] = pc + signext_imm; ++ next_pcs[nr++] = pc + 4; ++ break; ++ case OPCODE_BEQ: ++ case OPCODE_BNE: ++ case OPCODE_BLT: ++ case OPCODE_BGE: ++ case OPCODE_BLTU: ++ case OPCODE_BGEU: ++ imm = bits32(insn, 25, 10); ++ signext_imm = sign_extend64(imm << 2, 18); ++ next_pcs[nr++] = pc + signext_imm; ++ next_pcs[nr++] = pc + 4; ++ break; ++ case OPCODE_BEQZ: ++ case OPCODE_BNEZ: ++ imm = bits32(insn, 25, 10) + (bits32(insn, 4, 0) << 16); ++ signext_imm = sign_extend64(imm << 2, 23); ++ next_pcs[nr++] = pc + signext_imm; ++ next_pcs[nr++] = pc + 4; ++ break; ++ default: ++ next_pcs[nr++] = pc + 4; ++ break; ++ } ++ if (nr <= 0 || nr > 2) ++ goto fail; ++ if (nr == 2) { ++ if (next_pcs[1] == 0) ++ goto fail; ++ } ++ if (next_pcs[0] == 0) ++ goto fail; ++ ++ assert(nr == 1 || nr == 2); ++ return nr; ++ ++fail: ++ printf("nr=%d pc=%p\n", nr, pc); ++ printf("next_pcs=%p %p\n", next_pcs[0], next_pcs[1]); ++ ++ return nr; ++ ++} ++ ++enum sw_singlestep_status ++arch_sw_singlestep(struct process *proc, struct breakpoint *sbp, ++ int (*add_cb)(arch_addr_t, struct sw_singlestep_data *), ++ struct sw_singlestep_data *add_cb_data) ++{ ++ int nr; ++ arch_addr_t next_pcs[2] = {}; ++ arch_addr_t pc = get_instruction_pointer(proc); ++ nr = loongarch_get_next_pcs(proc, pc, next_pcs); ++ ++ while (nr-- > 0) { ++ arch_addr_t baddr = next_pcs[nr]; ++ if (DICT_HAS_KEY(proc->leader->breakpoints, &baddr)) { ++ fprintf(stderr, "skip %p %p\n", baddr, add_cb_data); ++ continue; ++ } ++ ++ if (add_cb(baddr, add_cb_data) < 0) ++ return SWS_FAIL; ++ } ++ debug(1, "PTRACE_CONT"); ++ ptrace(PTRACE_CONT, proc->pid, 0, 0); ++ return SWS_OK; ++} ++ ++int ++syscall_p(struct process *proc, int status, int *sysnum) ++{ ++ if (WIFSTOPPED(status) ++ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { ++ struct callstack_element *elem = NULL; ++ if (proc->callstack_depth > 0) ++ elem = proc->callstack + proc->callstack_depth - 1; ++ /* sysnum in $a7(r11) on loongarch */ ++ long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, ++ GPR_BASE + 11, 0); ++ if (ret == -1) { ++ if (errno) ++ return -1; ++ } ++ ++ *sysnum = ret; ++ ++ if (elem != NULL && elem->is_syscall ++ && elem->c_un.syscall == *sysnum) ++ return 2; ++ ++ if (*sysnum >= 0) ++ return 1; ++ } ++ return 0; ++} ++ ++size_t ++arch_type_sizeof(struct process *proc, struct arg_type_info *info) ++{ ++ if (proc == NULL) ++ return (size_t)-2; ++ ++ switch (info->type) { ++ case ARGTYPE_VOID: ++ return 0; ++ ++ case ARGTYPE_CHAR: ++ return 1; ++ ++ case ARGTYPE_SHORT: ++ case ARGTYPE_USHORT: ++ return 2; ++ ++ case ARGTYPE_INT: ++ case ARGTYPE_UINT: ++ return 4; ++ ++ case ARGTYPE_LONG: ++ case ARGTYPE_ULONG: ++ case ARGTYPE_POINTER: ++ return 8; ++ ++ case ARGTYPE_FLOAT: ++ return 4; ++ case ARGTYPE_DOUBLE: ++ return 8; ++ ++ case ARGTYPE_ARRAY: ++ case ARGTYPE_STRUCT: ++ /* Use default value. */ ++ return (size_t)-2; ++ ++ default: ++ //assert(info->type != info->type); ++ abort(); ++ } ++} ++ ++size_t ++arch_type_alignof(struct process *proc, struct arg_type_info *info) ++{ ++ if (proc == NULL) ++ return (size_t)-2; ++ ++ switch (info->type) { ++ ++ case ARGTYPE_CHAR: ++ return 1; ++ ++ case ARGTYPE_SHORT: ++ case ARGTYPE_USHORT: ++ return 2; ++ ++ case ARGTYPE_INT: ++ case ARGTYPE_UINT: ++ return 4; ++ ++ case ARGTYPE_LONG: ++ case ARGTYPE_ULONG: ++ case ARGTYPE_POINTER: ++ return 8; ++ ++ case ARGTYPE_FLOAT: ++ return 4; ++ case ARGTYPE_DOUBLE: ++ return 8; ++ ++ case ARGTYPE_ARRAY: ++ case ARGTYPE_STRUCT: ++ /* Use default value. */ ++ return (size_t)-2; ++ default: ++ //assert(info->type != info->type); ++ abort(); ++ } ++} +-- +2.41.0 + diff --git a/add-sw_64-support-not-upstream-makefile.patch b/add-sw_64-support-not-upstream-makefile.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e217422f207c95f1dcce464cf100c78d42b0d07 --- /dev/null +++ b/add-sw_64-support-not-upstream-makefile.patch @@ -0,0 +1,75 @@ +From 3ee3dc3d0ecd8c11cb62317a6bf66c247b2f385d Mon Sep 17 00:00:00 2001 +From: herengui +Date: Tue, 29 Aug 2023 09:30:56 +0800 +Subject: [PATCH 1/2] add sw_64 support not upstream makefile + +Signed-off-by: herengui +--- + configure | 3 ++- + configure.ac | 1 + + sysdeps/linux-gnu/Makefile.am | 2 +- + sysdeps/linux-gnu/Makefile.in | 2 +- + 4 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/configure b/configure +index b9f1b5e..7054313 100755 +--- a/configure ++++ b/configure +@@ -13143,7 +13143,7 @@ fi + + + +-ac_config_files="$ac_config_files Makefile sysdeps/Makefile sysdeps/linux-gnu/Makefile sysdeps/linux-gnu/alpha/Makefile sysdeps/linux-gnu/arm/Makefile sysdeps/linux-gnu/cris/Makefile sysdeps/linux-gnu/ia64/Makefile sysdeps/linux-gnu/m68k/Makefile sysdeps/linux-gnu/metag/Makefile sysdeps/linux-gnu/mips/Makefile sysdeps/linux-gnu/ppc/Makefile sysdeps/linux-gnu/s390/Makefile sysdeps/linux-gnu/sparc/Makefile sysdeps/linux-gnu/x86/Makefile testsuite/Makefile testsuite/ltrace.main/Makefile testsuite/ltrace.minor/Makefile testsuite/ltrace.torture/Makefile" ++ac_config_files="$ac_config_files Makefile sysdeps/Makefile sysdeps/linux-gnu/Makefile sysdeps/linux-gnu/alpha/Makefile sysdeps/linux-gnu/sw_64/Makefile sysdeps/linux-gnu/arm/Makefile sysdeps/linux-gnu/cris/Makefile sysdeps/linux-gnu/ia64/Makefile sysdeps/linux-gnu/m68k/Makefile sysdeps/linux-gnu/metag/Makefile sysdeps/linux-gnu/mips/Makefile sysdeps/linux-gnu/ppc/Makefile sysdeps/linux-gnu/s390/Makefile sysdeps/linux-gnu/sparc/Makefile sysdeps/linux-gnu/x86/Makefile testsuite/Makefile testsuite/ltrace.main/Makefile testsuite/ltrace.minor/Makefile testsuite/ltrace.torture/Makefile" + + cat >confcache <<\_ACEOF + # This file is a shell script that caches the results of configure +@@ -14163,6 +14163,7 @@ do + "sysdeps/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/Makefile" ;; + "sysdeps/linux-gnu/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/Makefile" ;; + "sysdeps/linux-gnu/alpha/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/alpha/Makefile" ;; ++ "sysdeps/linux-gnu/sw_64/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/sw_64/Makefile" ;; + "sysdeps/linux-gnu/arm/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/arm/Makefile" ;; + "sysdeps/linux-gnu/cris/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/cris/Makefile" ;; + "sysdeps/linux-gnu/ia64/Makefile") CONFIG_FILES="$CONFIG_FILES sysdeps/linux-gnu/ia64/Makefile" ;; +diff --git a/configure.ac b/configure.ac +index 205457e..bc58d81 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -404,6 +404,7 @@ AC_CONFIG_FILES([ + sysdeps/linux-gnu/Makefile + sysdeps/linux-gnu/aarch64/Makefile + sysdeps/linux-gnu/alpha/Makefile ++ sysdeps/linux-gnu/sw_64/Makefile + sysdeps/linux-gnu/arm/Makefile + sysdeps/linux-gnu/cris/Makefile + sysdeps/linux-gnu/ia64/Makefile +diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am +index 7d17020..bff940e 100644 +--- a/sysdeps/linux-gnu/Makefile.am ++++ b/sysdeps/linux-gnu/Makefile.am +@@ -18,7 +18,7 @@ + # 02110-1301 USA + + DIST_SUBDIRS = aarch64 alpha arm cris ia64 loongarch m68k metag mips \ +- ppc s390 sparc x86 ++ ppc s390 sparc x86 sw_64 + + SUBDIRS = \ + $(HOST_CPU) +diff --git a/sysdeps/linux-gnu/Makefile.in b/sysdeps/linux-gnu/Makefile.in +index 8a4f4d6..11c8ac5 100644 +--- a/sysdeps/linux-gnu/Makefile.in ++++ b/sysdeps/linux-gnu/Makefile.in +@@ -353,7 +353,7 @@ target_alias = @target_alias@ + top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ +-DIST_SUBDIRS = alpha arm cris ia64 m68k metag mips ppc s390 sparc x86 ++DIST_SUBDIRS = sw_64 alpha arm cris ia64 m68k metag mips ppc s390 sparc x86 + SUBDIRS = \ + $(HOST_CPU) + +-- +2.41.0 + diff --git a/add-sw_64-support-not-upstream-sysdeps.patch b/add-sw_64-support-not-upstream-sysdeps.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f8280d7da807ed0fa3da2cd87bf678eef6f594c --- /dev/null +++ b/add-sw_64-support-not-upstream-sysdeps.patch @@ -0,0 +1,1427 @@ +From d1843238dceda9b9d2196e384dad43aabfcdae82 Mon Sep 17 00:00:00 2001 +From: herengui +Date: Tue, 29 Aug 2023 09:31:13 +0800 +Subject: [PATCH 2/2] add loongarch support not upstream sysdeps + +Signed-off-by: herengui +--- + sysdeps/linux-gnu/sw_64/Makefile.am | 34 ++ + sysdeps/linux-gnu/sw_64/Makefile.in | 629 +++++++++++++++++++++++++++ + sysdeps/linux-gnu/sw_64/arch.h | 29 ++ + sysdeps/linux-gnu/sw_64/plt.c | 36 ++ + sysdeps/linux-gnu/sw_64/ptrace.h | 21 + + sysdeps/linux-gnu/sw_64/regs.c | 61 +++ + sysdeps/linux-gnu/sw_64/signalent.h | 52 +++ + sysdeps/linux-gnu/sw_64/syscallent.h | 384 ++++++++++++++++ + sysdeps/linux-gnu/sw_64/trace.c | 97 +++++ + 9 files changed, 1343 insertions(+) + create mode 100644 sysdeps/linux-gnu/sw_64/Makefile.am + create mode 100644 sysdeps/linux-gnu/sw_64/Makefile.in + create mode 100644 sysdeps/linux-gnu/sw_64/arch.h + create mode 100644 sysdeps/linux-gnu/sw_64/plt.c + create mode 100644 sysdeps/linux-gnu/sw_64/ptrace.h + create mode 100644 sysdeps/linux-gnu/sw_64/regs.c + create mode 100644 sysdeps/linux-gnu/sw_64/signalent.h + create mode 100644 sysdeps/linux-gnu/sw_64/syscallent.h + create mode 100644 sysdeps/linux-gnu/sw_64/trace.c + +diff --git a/sysdeps/linux-gnu/sw_64/Makefile.am b/sysdeps/linux-gnu/sw_64/Makefile.am +new file mode 100644 +index 0000000..5c6ecc2 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/Makefile.am +@@ -0,0 +1,34 @@ ++# This file is part of ltrace. ++# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix ++# ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++# 02110-1301 USA ++ ++noinst_LTLIBRARIES = \ ++ ../libcpu.la ++ ++___libcpu_la_SOURCES = \ ++ plt.c \ ++ regs.c \ ++ trace.c ++ ++noinst_HEADERS = \ ++ arch.h \ ++ ptrace.h \ ++ signalent.h \ ++ syscallent.h ++ ++MAINTAINERCLEANFILES = \ ++ Makefile.in +diff --git a/sysdeps/linux-gnu/sw_64/Makefile.in b/sysdeps/linux-gnu/sw_64/Makefile.in +new file mode 100644 +index 0000000..8d71f51 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/Makefile.in +@@ -0,0 +1,629 @@ ++# Makefile.in generated by automake 1.14.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994-2013 Free Software Foundation, Inc. ++ ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++# This file is part of ltrace. ++# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix ++# ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++# 02110-1301 USA ++ ++ ++VPATH = @srcdir@ ++am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' ++am__make_running_with_option = \ ++ case $${target_option-} in \ ++ ?) ;; \ ++ *) echo "am__make_running_with_option: internal error: invalid" \ ++ "target option '$${target_option-}' specified" >&2; \ ++ exit 1;; \ ++ esac; \ ++ has_opt=no; \ ++ sane_makeflags=$$MAKEFLAGS; \ ++ if $(am__is_gnu_make); then \ ++ sane_makeflags=$$MFLAGS; \ ++ else \ ++ case $$MAKEFLAGS in \ ++ *\\[\ \ ]*) \ ++ bs=\\; \ ++ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ ++ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ ++ esac; \ ++ fi; \ ++ skip_next=no; \ ++ strip_trailopt () \ ++ { \ ++ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ ++ }; \ ++ for flg in $$sane_makeflags; do \ ++ test $$skip_next = yes && { skip_next=no; continue; }; \ ++ case $$flg in \ ++ *=*|--*) continue;; \ ++ -*I) strip_trailopt 'I'; skip_next=yes;; \ ++ -*I?*) strip_trailopt 'I';; \ ++ -*O) strip_trailopt 'O'; skip_next=yes;; \ ++ -*O?*) strip_trailopt 'O';; \ ++ -*l) strip_trailopt 'l'; skip_next=yes;; \ ++ -*l?*) strip_trailopt 'l';; \ ++ -[dEDm]) skip_next=yes;; \ ++ -[JT]) skip_next=yes;; \ ++ esac; \ ++ case $$flg in \ ++ *$$target_option*) has_opt=yes; break;; \ ++ esac; \ ++ done; \ ++ test $$has_opt = yes ++am__make_dryrun = (target_option=n; $(am__make_running_with_option)) ++am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++subdir = sysdeps/linux-gnu/sw_64 ++DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ ++ $(top_srcdir)/config/autoconf/depcomp $(noinst_HEADERS) ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ ++ $(top_srcdir)/config/m4/ltoptions.m4 \ ++ $(top_srcdir)/config/m4/ltsugar.m4 \ ++ $(top_srcdir)/config/m4/ltversion.m4 \ ++ $(top_srcdir)/config/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++LTLIBRARIES = $(noinst_LTLIBRARIES) ++___libcpu_la_LIBADD = ++am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo ++___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS) ++AM_V_lt = $(am__v_lt_@AM_V@) ++am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) ++am__v_lt_0 = --silent ++am__v_lt_1 = ++am__dirstamp = $(am__leading_dot)dirstamp ++AM_V_P = $(am__v_P_@AM_V@) ++am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) ++am__v_P_0 = false ++am__v_P_1 = : ++AM_V_GEN = $(am__v_GEN_@AM_V@) ++am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) ++am__v_GEN_0 = @echo " GEN " $@; ++am__v_GEN_1 = ++AM_V_at = $(am__v_at_@AM_V@) ++am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) ++am__v_at_0 = @ ++am__v_at_1 = ++DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) ++depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp ++am__depfiles_maybe = depfiles ++am__mv = mv -f ++COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ ++ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ ++ $(AM_CFLAGS) $(CFLAGS) ++AM_V_CC = $(am__v_CC_@AM_V@) ++am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) ++am__v_CC_0 = @echo " CC " $@; ++am__v_CC_1 = ++CCLD = $(CC) ++LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ ++ $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++AM_V_CCLD = $(am__v_CCLD_@AM_V@) ++am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) ++am__v_CCLD_0 = @echo " CCLD " $@; ++am__v_CCLD_1 = ++SOURCES = $(___libcpu_la_SOURCES) ++DIST_SOURCES = $(___libcpu_la_SOURCES) ++am__can_run_installinfo = \ ++ case $$AM_UPDATE_INFO_DIR in \ ++ n|no|NO) false;; \ ++ *) (install-info --version) >/dev/null 2>&1;; \ ++ esac ++HEADERS = $(noinst_HEADERS) ++am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) ++# Read a list of newline-separated strings from the standard input, ++# and print each of them once, without duplicates. Input order is ++# *not* preserved. ++am__uniquify_input = $(AWK) '\ ++ BEGIN { nonempty = 0; } \ ++ { items[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in items) print i; }; } \ ++' ++# Make sure the list of sources is unique. This is necessary because, ++# e.g., the same source file might be shared among _SOURCES variables ++# for different programs/libraries. ++am__define_uniq_tagged_files = \ ++ list='$(am__tagged_files)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | $(am__uniquify_input)` ++ETAGS = etags ++CTAGS = ctags ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = @ACLOCAL@ ++AMTAR = @AMTAR@ ++AM_CFLAGS = @AM_CFLAGS@ ++AM_CPPFLAGS = @AM_CPPFLAGS@ ++AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ++AM_LDFLAGS = @AM_LDFLAGS@ ++AR = @AR@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CC = @CC@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEFS = @DEFS@ ++DEPDIR = @DEPDIR@ ++DLLTOOL = @DLLTOOL@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++EXEEXT = @EXEEXT@ ++FGREP = @FGREP@ ++GREP = @GREP@ ++HAVE_VALGRIND = @HAVE_VALGRIND@ ++HOST_CPU = @HOST_CPU@ ++HOST_OS = @HOST_OS@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAINT = @MAINT@ ++MAKEINFO = @MAKEINFO@ ++MANIFEST_TOOL = @MANIFEST_TOOL@ ++MKDIR_P = @MKDIR_P@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++RANLIB = @RANLIB@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SHELL = @SHELL@ ++STRIP = @STRIP@ ++VERSION = @VERSION@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_AR = @ac_ct_AR@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++libdir = @libdir@ ++libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@ ++liberty_LIBS = @liberty_LIBS@ ++libexecdir = @libexecdir@ ++libstdcxx_LIBS = @libstdcxx_LIBS@ ++libsupcxx_LIBS = @libsupcxx_LIBS@ ++libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@ ++libunwind_LIBS = @libunwind_LIBS@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++noinst_LTLIBRARIES = \ ++ ../libcpu.la ++ ++___libcpu_la_SOURCES = \ ++ plt.c \ ++ regs.c \ ++ trace.c ++ ++noinst_HEADERS = \ ++ arch.h \ ++ ptrace.h \ ++ signalent.h \ ++ syscallent.h ++ ++MAINTAINERCLEANFILES = \ ++ Makefile.in ++ ++all: all-am ++ ++.SUFFIXES: ++.SUFFIXES: .c .lo .o .obj ++$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/sw_64/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign sysdeps/linux-gnu/sw_64/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++clean-noinstLTLIBRARIES: ++ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) ++ @list='$(noinst_LTLIBRARIES)'; \ ++ locs=`for p in $$list; do echo $$p; done | \ ++ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ ++ sort -u`; \ ++ test -z "$$locs" || { \ ++ echo rm -f $${locs}; \ ++ rm -f $${locs}; \ ++ } ++../$(am__dirstamp): ++ @$(MKDIR_P) .. ++ @: > ../$(am__dirstamp) ++ ++../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) $(EXTRA____libcpu_la_DEPENDENCIES) ../$(am__dirstamp) ++ $(AM_V_CCLD)$(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS) ++ ++mostlyclean-compile: ++ -rm -f *.$(OBJEXT) ++ ++distclean-compile: ++ -rm -f *.tab.c ++ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@ ++ ++.c.o: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< ++ ++.c.obj: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ++ ++.c.lo: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++ -rm -rf ../.libs ../_libs ++ ++ID: $(am__tagged_files) ++ $(am__define_uniq_tagged_files); mkid -fID $$unique ++tags: tags-am ++TAGS: tags ++ ++tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) ++ set x; \ ++ here=`pwd`; \ ++ $(am__define_uniq_tagged_files); \ ++ shift; \ ++ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ ++ test -n "$$unique" || unique=$$empty_fix; \ ++ if test $$# -gt 0; then \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ "$$@" $$unique; \ ++ else \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ $$unique; \ ++ fi; \ ++ fi ++ctags: ctags-am ++ ++CTAGS: ctags ++ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) ++ $(am__define_uniq_tagged_files); \ ++ test -z "$(CTAGS_ARGS)$$unique" \ ++ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ ++ $$unique ++ ++GTAGS: ++ here=`$(am__cd) $(top_builddir) && pwd` \ ++ && $(am__cd) $(top_srcdir) \ ++ && gtags -i $(GTAGS_ARGS) "$$here" ++cscopelist: cscopelist-am ++ ++cscopelist-am: $(am__tagged_files) ++ list='$(am__tagged_files)'; \ ++ case "$(srcdir)" in \ ++ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ ++ *) sdir=$(subdir)/$(srcdir) ;; \ ++ esac; \ ++ for i in $$list; do \ ++ if test -f "$$i"; then \ ++ echo "$(subdir)/$$i"; \ ++ else \ ++ echo "$$sdir/$$i"; \ ++ fi; \ ++ done >> $(top_builddir)/cscope.files ++ ++distclean-tags: ++ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile $(LTLIBRARIES) $(HEADERS) ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ if test -z '$(STRIP)'; then \ ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ install; \ ++ else \ ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ ++ fi ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ -rm -f ../$(am__dirstamp) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ ++ mostlyclean-am ++ ++distclean: distclean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++distclean-am: clean-am distclean-compile distclean-generic \ ++ distclean-tags ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-compile mostlyclean-generic \ ++ mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ ++ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ++ ctags-am distclean distclean-compile distclean-generic \ ++ distclean-libtool distclean-tags distdir dvi dvi-am html \ ++ html-am info info-am install install-am install-data \ ++ install-data-am install-dvi install-dvi-am install-exec \ ++ install-exec-am install-html install-html-am install-info \ ++ install-info-am install-man install-pdf install-pdf-am \ ++ install-ps install-ps-am install-strip installcheck \ ++ installcheck-am installdirs maintainer-clean \ ++ maintainer-clean-generic mostlyclean mostlyclean-compile \ ++ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ ++ tags tags-am uninstall uninstall-am ++ ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +diff --git a/sysdeps/linux-gnu/sw_64/arch.h b/sysdeps/linux-gnu/sw_64/arch.h +new file mode 100644 +index 0000000..55400a4 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/arch.h +@@ -0,0 +1,29 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2004 Juan Cespedes ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#define BREAKPOINT_VALUE { 0x80, 0x00, 0x00, 0x00 } ++#define BREAKPOINT_LENGTH 4 ++#define DECR_PC_AFTER_BREAK 4 ++#define ARCH_ENDIAN_LITTLE ++ ++#define LT_ELFCLASS ELFCLASS64 ++#define LT_ELF_MACHINE EM_SW_64 ++#define LT_ELFCLASS2 ELFCLASS64 ++#define LT_ELF_MACHINE2 EM_FAKE_SW_64 +diff --git a/sysdeps/linux-gnu/sw_64/plt.c b/sysdeps/linux-gnu/sw_64/plt.c +new file mode 100644 +index 0000000..2e6342d +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/plt.c +@@ -0,0 +1,36 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2004,2008,2009 Juan Cespedes ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include "proc.h" ++#include "common.h" ++#include "library.h" ++ ++GElf_Addr ++arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela) ++{ ++ return lte->plt_addr + ndx * 12 + 32; ++} ++ ++void * ++sym2addr(struct process *proc, struct library_symbol *sym) ++{ ++ return sym->enter_addr; ++} +diff --git a/sysdeps/linux-gnu/sw_64/ptrace.h b/sysdeps/linux-gnu/sw_64/ptrace.h +new file mode 100644 +index 0000000..ad7e0d6 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/ptrace.h +@@ -0,0 +1,21 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2004 Juan Cespedes ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include +diff --git a/sysdeps/linux-gnu/sw_64/regs.c b/sysdeps/linux-gnu/sw_64/regs.c +new file mode 100644 +index 0000000..9ccd8f2 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/regs.c +@@ -0,0 +1,61 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2013 Petr Machata, Red Hat Inc. ++ * Copyright (C) 2004,2008,2009 Juan Cespedes ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#include "proc.h" ++#include "common.h" ++ ++#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) ++# define PTRACE_PEEKUSER PTRACE_PEEKUSR ++#endif ++ ++#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) ++# define PTRACE_POKEUSER PTRACE_POKEUSR ++#endif ++ ++void * ++get_instruction_pointer(struct process *proc) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 64 /* REG_PC */ , 0); ++} ++ ++void ++set_instruction_pointer(struct process *proc, void *addr) ++{ ++ ptrace(PTRACE_POKEUSER, proc->pid, 64 /* REG_PC */ , addr); ++} ++ ++void * ++get_stack_pointer(struct process *proc) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 30 /* REG_FP */ , 0); ++} ++ ++void * ++get_return_addr(struct process *proc, void *stack_pointer) ++{ ++ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 26 /* RA */ , 0); ++} +diff --git a/sysdeps/linux-gnu/sw_64/signalent.h b/sysdeps/linux-gnu/sw_64/signalent.h +new file mode 100644 +index 0000000..e9588fa +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/signalent.h +@@ -0,0 +1,52 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2006 Ian Wienand ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++"SIG_0", /* 0 */ ++ "SIGHUP", /* 1 */ ++ "SIGINT", /* 2 */ ++ "SIGQUIT", /* 3 */ ++ "SIGILL", /* 4 */ ++ "SIGTRAP", /* 5 */ ++ "SIGABRT", /* 6 */ ++ "SIGEMT", /* 7 */ ++ "SIGFPE", /* 8 */ ++ "SIGKILL", /* 9 */ ++ "SIGBUS", /* 10 */ ++ "SIGSEGV", /* 11 */ ++ "SIGSYS", /* 12 */ ++ "SIGPIPE", /* 13 */ ++ "SIGALRM", /* 14 */ ++ "SIGTERM", /* 15 */ ++ "SIGURG", /* 16 */ ++ "SIGSTOP", /* 17 */ ++ "SIGTSTP", /* 18 */ ++ "SIGCONT", /* 19 */ ++ "SIGCHLD", /* 20 */ ++ "SIGTTIN", /* 21 */ ++ "SIGTTOU", /* 22 */ ++ "SIGIO", /* 23 */ ++ "SIGXCPU", /* 24 */ ++ "SIGXFSZ", /* 25 */ ++ "SIGVTALRM", /* 26 */ ++ "SIGPROF", /* 27 */ ++ "SIGWINCH", /* 28 */ ++ "SIGINFO", /* 29 */ ++ "SIGUSR1", /* 30 */ ++ "SIGUSR2", /* 31 */ +diff --git a/sysdeps/linux-gnu/sw_64/syscallent.h b/sysdeps/linux-gnu/sw_64/syscallent.h +new file mode 100644 +index 0000000..586f4a2 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/syscallent.h +@@ -0,0 +1,384 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2006 Ian Wienand ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++ "exit", /* 1 */ ++ "fork", /* 2 */ ++ "read", /* 3 */ ++ "write", /* 4 */ ++ "close", /* 6 */ ++ "link", /* 9 */ ++ "unlink", /* 10 */ ++ "chdir", /* 12 */ ++ "fchdir", /* 13 */ ++ "mknod", /* 14 */ ++ "chmod", /* 15 */ ++ "chown", /* 16 */ ++ "brk", /* 17 */ ++ "lseek", /* 19 */ ++ "getxpid", /* 20 */ ++ "umount", /* 22 */ ++ "setuid", /* 23 */ ++ "getxuid", /* 24 */ ++ "ptrace", /* 26 */ ++ "access", /* 33 */ ++ "sync", /* 36 */ ++ "kill", /* 37 */ ++ "setpgid", /* 39 */ ++ "dup", /* 41 */ ++ "pipe", /* 42 */ ++ "open", /* 45 */ ++ "getxgid", /* 47 */ ++ "odd_sigprocmask", /* 48 */ ++ "acct", /* 51 */ ++ "sigpending", /* 52 */ ++ "ioctl", /* 54 */ ++ "symlink", /* 57 */ ++ "readlink", /* 58 */ ++ "execve", /* 59 */ ++ "umask", /* 60 */ ++ "chroot", /* 61 */ ++ "getpgrp", /* 63 */ ++ "vfork", /* 66 */ ++ "stat", /* 67 */ ++ "lstat", /* 68 */ ++ "mmap", /* 71 */ ++ "munmap", /* 73 */ ++ "mprotect", /* 74 */ ++ "madvise", /* 75 */ ++ "vhangup", /* 76 */ ++ "getgroups", /* 79 */ ++ "setgroups", /* 80 */ ++ "setpgrp", /* 82 */ ++ "gethostname", /* 87 */ ++ "sethostname", /* 88 */ ++ "dup2", /* 90 */ ++ "fstat", /* 91 */ ++ "fcntl", /* 92 */ ++ "poll", /* 94 */ ++ "fsync", /* 95 */ ++ "setpriority", /* 96 */ ++ "socket", /* 97 */ ++ "connect", /* 98 */ ++ "accept", /* 99 */ ++ "osf_getpriority", /* 100 */ ++ "send", /* 101 */ ++ "recv", /* 102 */ ++ "sigreturn", /* 103 */ ++ "bind", /* 104 */ ++ "setsockopt", /* 105 */ ++ "listen", /* 106 */ ++ "sigsuspend", /* 111 */ ++ "recvmsg", /* 113 */ ++ "sendmsg", /* 114 */ ++ "getsockopt", /* 118 */ ++ "SYS_119", /* 119 */ ++ "readv", /* 120 */ ++ "writev", /* 121 */ ++ "fchown", /* 123 */ ++ "fchmod", /* 124 */ ++ "recvfrom", /* 125 */ ++ "setreuid", /* 126 */ ++ "setregid", /* 127 */ ++ "rename", /* 128 */ ++ "truncate", /* 129 */ ++ "ftruncate", /* 130 */ ++ "flock", /* 131 */ ++ "setgid", /* 132 */ ++ "sendto", /* 133 */ ++ "shutdown", /* 134 */ ++ "socketpair", /* 135 */ ++ "mkdir", /* 136 */ ++ "rmdir", /* 137 */ ++ "getpeername", /* 141 */ ++ "getrlimit", /* 144 */ ++ "setrlimit", /* 145 */ ++ "setsid", /* 147 */ ++ "quotactl", /* 148 */ ++ "getsockname", /* 150 */ ++ "sigaction", /* 156 */ ++ "setdomainname", /* 166 */ ++ "bpf", /* 170 */ ++ "userfaultfd", /* 171 */ ++ "membarrier", /* 172 */ ++ "mlock2", /* 173 */ ++ "getpid", /* 174 */ ++ "getppid", /* 175 */ ++ "getuid", /* 176 */ ++ "geteuid", /* 177 */ ++ "getgid", /* 178 */ ++ "getegid", /* 179 */ ++ "msgctl", /* 200 */ ++ "msgget", /* 201 */ ++ "msgrcv", /* 202 */ ++ "msgsnd", /* 203 */ ++ "semctl", /* 204 */ ++ "semget", /* 205 */ ++ "semop", /* 206 */ ++ "lchown", /* 208 */ ++ "osf_shmat", /* 209 */ ++ "shmctl", /* 210 */ ++ "shmdt", /* 211 */ ++ "shmget", /* 212 */ ++ "msync", /* 217 */ ++ "statfs64", /* 229 */ ++ "fstatfs64", /* 230 */ ++ "getpgid", /* 233 */ ++ "getsid", /* 234 */ ++ "sigaltstack", /* 235 */ ++ "sysfs", /* 254 */ ++ "getsysinfo", /* 256 */ ++ "setsysinfo", /* 257 */ ++ "pidfd_send_signal", /* 271 */ ++ "io_uring_setup", /* 272 */ ++ "io_uring_enter", /* 273 */ ++ "io_uring_register", /* 274 */ ++ "open_tree", /* 275 */ ++ "move_mount", /* 276 */ ++ "fsopen", /* 277 */ ++ "fsconfig", /* 278 */ ++ "fsmount", /* 279 */ ++ "fspick", /* 280 */ ++ "pidfd_open", /* 281 */ ++ "clone3", /* 282 */ ++ "close_range", /* 283 */ ++ "openat2", /* 284 */ ++ "pidfd_getfd", /* 285 */ ++ "faccessat2", /* 286 */ ++ "process_madvise", /* 287 */ ++ "pkey_mprotect", /* 288 */ ++ "pkey_alloc", /* 289 */ ++ "pkey_free", /* 290 */ ++ "getpriority", /* 298 */ ++ "sigprocmask", /* 299 */ ++ "bdflush", /* 300 */ ++ "mount", /* 302 */ ++ "swapoff", /* 304 */ ++ "getdents", /* 305 */ ++ "create_module", /* 306 */ ++ "init_module", /* 307 */ ++ "delete_module", /* 308 */ ++ "get_kernel_syms", /* 309 */ ++ "syslog", /* 310 */ ++ "reboot", /* 311 */ ++ "clone", /* 312 */ ++ "uselib", /* 313 */ ++ "mlock", /* 314 */ ++ "munlock", /* 315 */ ++ "mlockall", /* 316 */ ++ "munlockall", /* 317 */ ++ "sysinfo", /* 318 */ ++ "oldumount", /* 321 */ ++ "swapon", /* 322 */ ++ "times", /* 323 */ ++ "personality", /* 324 */ ++ "setfsuid", /* 325 */ ++ "setfsgid", /* 326 */ ++ "ustat", /* 327 */ ++ "statfs", /* 328 */ ++ "fstatfs", /* 329 */ ++ "sched_setparam", /* 330 */ ++ "sched_getparam", /* 331 */ ++ "sched_setscheduler", /* 332 */ ++ "sched_getscheduler", /* 333 */ ++ "sched_yield", /* 334 */ ++ "sched_get_priority_max", /* 335 */ ++ "sched_get_priority_min", /* 336 */ ++ "sched_rr_get_interval", /* 337 */ ++ "afs_syscall", /* 338 */ ++ "uname", /* 339 */ ++ "nanosleep", /* 340 */ ++ "mremap", /* 341 */ ++ "nfsservctl", /* 342 */ ++ "setresuid", /* 343 */ ++ "getresuid", /* 344 */ ++ "pciconfig_read", /* 345 */ ++ "pciconfig_write", /* 346 */ ++ "query_module", /* 347 */ ++ "prctl", /* 348 */ ++ "pread", /* 349 */ ++ "pwrite", /* 350 */ ++ "rt_sigreturn", /* 351 */ ++ "rt_sigaction", /* 352 */ ++ "rt_sigprocmask", /* 353 */ ++ "rt_sigpending", /* 354 */ ++ "rt_sigtimedwait", /* 355 */ ++ "rt_sigqueueinfo", /* 356 */ ++ "rt_sigsuspend", /* 357 */ ++ "select", /* 358 */ ++ "gettimeofday", /* 359 */ ++ "settimeofday", /* 360 */ ++ "getitimer", /* 361 */ ++ "setitimer", /* 362 */ ++ "utimes", /* 363 */ ++ "getrusage", /* 364 */ ++ "wait4", /* 365 */ ++ "adjtimex", /* 366 */ ++ "getcwd", /* 367 */ ++ "capget", /* 368 */ ++ "capset", /* 369 */ ++ "sendfile", /* 370 */ ++ "setresgid", /* 371 */ ++ "getresgid", /* 372 */ ++ "dipc", /* 373, not implemented */ ++ "pivot_root", /* 374 */ ++ "mincore", /* 375 */ ++ "pciconfig_iobase", /* 376 */ ++ "getdents64", /* 377 */ ++ "gettid", /* 378 */ ++ "readahead", /* 379 */ ++ "tkill", /* 381 */ ++ "setxattr", /* 382 */ ++ "lsetxattr", /* 383 */ ++ "fsetxattr", /* 384 */ ++ "getxattr", /* 385 */ ++ "lgetxattr", /* 386 */ ++ "fgetxattr", /* 387 */ ++ "listxattr", /* 388 */ ++ "llistxattr", /* 389 */ ++ "flistxattr", /* 390 */ ++ "removexattr", /* 391 */ ++ "lremovexattr", /* 392 */ ++ "fremovexattr", /* 393 */ ++ "futex", /* 394 */ ++ "sched_setaffinity", /* 395 */ ++ "sched_getaffinity", /* 396 */ ++ "tuxcall", /* 397 */ ++ "io_setup", /* 398 */ ++ "io_destroy", /* 399 */ ++ "io_getevents", /* 400 */ ++ "io_submit", /* 401 */ ++ "io_cancel", /* 402 */ ++ "SYS_403", /* 403 */ ++ "SYS_404", /* 404 */ ++ "exit_group", /* 405 */ ++ "lookup_dcookie", /* 406 */ ++ "epoll_create", /* 407 */ ++ "epoll_ctl", /* 408 */ ++ "epoll_wait", /* 409 */ ++ "remap_file_pages", /* 410 */ ++ "set_tid_address", /* 411 */ ++ "restart_syscall", /* 412 */ ++ "fadvise", /* 413 */ ++ "timer_create", /* 414 */ ++ "timer_settime", /* 415 */ ++ "timer_gettime", /* 416 */ ++ "timer_getoverrun", /* 417 */ ++ "timer_delete", /* 418 */ ++ "clock_settime", /* 419 */ ++ "clock_gettime", /* 420 */ ++ "clock_getres", /* 421 */ ++ "clock_nanosleep", /* 422 */ ++ "semtimedop", /* 423 */ ++ "tgkill", /* 424 */ ++ "stat64", /* 425 */ ++ "lstat64", /* 426 */ ++ "fstat64", /* 427 */ ++ "vserver", /* 428 */ ++ "mbind", /* 429 */ ++ "get_mempolicy", /* 430 */ ++ "set_mempolicy", /* 431 */ ++ "mq_open", /* 432 */ ++ "mq_unlink", /* 433 */ ++ "mq_timedsend", /* 434 */ ++ "mq_timedreceive", /* 435 */ ++ "mq_notify", /* 436 */ ++ "mq_getsetattr", /* 437 */ ++ "waitid", /* 438 */ ++ "add_key", /* 439 */ ++ "request_key", /* 440 */ ++ "keyctl", /* 441 */ ++ "request_key", /* 442 */ ++ "ioprio_set", /* 443 */ ++ "inotify_init", /* 444 */ ++ "inotify_add_watch", /* 445 */ ++ "inotify_rm_watch", /* 446 */ ++ "fdatasync", /* 447 */ ++ "kexec_load", /* 448 */ ++ "migrate_pages", /* 449 */ ++ "openat", /* 450 */ ++ "mkdirat", /* 451 */ ++ "mknodat", /* 452 */ ++ "fchownat", /* 453 */ ++ "futimesat", /* 454 */ ++ "fstatat64", /* 455 */ ++ "unlinkat", /* 456 */ ++ "renameat", /* 457 */ ++ "linkat", /* 458 */ ++ "symlinkat", /* 459 */ ++ "readlinkat", /* 460 */ ++ "fchmodat", /* 461 */ ++ "faccessat", /* 462 */ ++ "pselect6", /* 463 */ ++ "ppoll", /* 464 */ ++ "unshare", /* 465 */ ++ "set_robust_list", /* 466 */ ++ "get_robust_list", /* 467 */ ++ "splice", /* 468 */ ++ "sync_file_range", /* 469 */ ++ "tee", /* 470 */ ++ "vmsplice", /* 471 */ ++ "move_pages", /* 472 */ ++ "getcpu", /* 473 */ ++ "epoll_pwait", /* 474 */ ++ "utimensat", /* 475 */ ++ "signalfd", /* 476 */ ++ "timerfd", /* 477 */ ++ "eventfd", /* 478 */ ++ "recvmmsg", /* 479 */ ++ "fallocate", /* 480 */ ++ "timerfd_create", /* 481 */ ++ "timerfd_settime", /* 482 */ ++ "timerfd_gettime", /* 483 */ ++ "signalfd4", /* 484 */ ++ "eventfd2", /* 485 */ ++ "epoll_create1", /* 486 */ ++ "dup3", /* 487 */ ++ "pipe2", /* 488 */ ++ "inotify_init1", /* 489 */ ++ "preadv", /* 490 */ ++ "pwritev", /* 491 */ ++ "rt_tgsigqueueinfo", /* 492 */ ++ "perf_event_open", /* 493 */ ++ "fanotify_init", /* 494 */ ++ "fanotify_mark", /* 495 */ ++ "prlimit64", /* 496 */ ++ "name_to_handle_at", /* 497 */ ++ "open_by_handle_at", /* 498 */ ++ "clock_adjtime", /* 499 */ ++ "syncfs", /* 500 */ ++ "setns", /* 501 */ ++ "accept4", /* 502 */ ++ "sendmmsg", /* 503 */ ++ "process_vm_readv", /* 504 */ ++ "process_vm_writev", /* 505 */ ++ "kcmp", /* 506 */ ++ "finit_module", /* 507 */ ++ "sched_setattr", /* 508 */ ++ "sched_getattr", /* 509 */ ++ "renameat2", /* 510 */ ++ "getrandom", /* 511 */ ++ "memfd_create", /* 512 */ ++ "execveat", /* 513 */ ++ "seccomp", /* 514 */ ++ "copy_file_range", /* 515 */ ++ "preadv2", /* 516 */ ++ "pwritev2", /* 517 */ ++ "statx" /* 518 */ ++ +diff --git a/sysdeps/linux-gnu/sw_64/trace.c b/sysdeps/linux-gnu/sw_64/trace.c +new file mode 100644 +index 0000000..c6f7494 +--- /dev/null ++++ b/sysdeps/linux-gnu/sw_64/trace.c +@@ -0,0 +1,97 @@ ++/* ++ * This file is part of ltrace. ++ * Copyright (C) 2004,2008,2009 Juan Cespedes ++ * Copyright (C) 2006 Ian Wienand ++ * ++ * 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 2 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "proc.h" ++#include "common.h" ++#include "debug.h" ++ ++#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) ++# define PTRACE_PEEKUSER PTRACE_PEEKUSR ++#endif ++ ++#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) ++# define PTRACE_POKEUSER PTRACE_POKEUSR ++#endif ++ ++void ++get_arch_dep(struct process *proc) ++{ ++} ++ ++/* Returns 1 if syscall, 2 if sysret, 0 otherwise. ++ */ ++int ++syscall_p(struct process *proc, int status, int *sysnum) ++{ ++ if (WIFSTOPPED(status) ++ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { ++ char *ip = get_instruction_pointer(proc) - 4; ++ long x = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); ++ debug(2, "instr: %016lx", x); ++ if ((x & 0xffffffff) != 0x00000083) ++ return 0; ++ *sysnum = ++ ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */ , 0); ++ if (proc->callstack_depth > 0 && ++ proc->callstack[proc->callstack_depth - 1].is_syscall && ++ proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { ++ return 2; ++ } ++ if (*sysnum >= 0 && *sysnum < 500) { ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++long ++gimme_arg(enum tof type, struct process *proc, int arg_num, ++ struct arg_type_info *info) ++{ ++ if (arg_num == -1) { /* return value */ ++ return ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */ , 0); ++ } ++ ++ if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { ++ if (arg_num <= 5) ++ return ptrace(PTRACE_PEEKUSER, proc->pid, ++ arg_num + 16 /* REG_A0 */ , 0); ++ else ++ return ptrace(PTRACE_PEEKTEXT, proc->pid, ++ proc->stack_pointer + 8 * (arg_num - 6), ++ 0); ++ } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { ++ return ptrace(PTRACE_PEEKUSER, proc->pid, ++ arg_num + 16 /* REG_A0 */ , 0); ++ } else { ++ fprintf(stderr, "gimme_arg called with wrong arguments\n"); ++ exit(1); ++ } ++ return 0; ++} +-- +2.41.0 + diff --git a/ltrace.spec b/ltrace.spec index 2e4954104361a2912a8cab2e0049558e0a4b12c8..ddc8628e26eb0fbc72b5dd23f216fad70f67c281 100644 --- a/ltrace.spec +++ b/ltrace.spec @@ -1,6 +1,6 @@ name: ltrace Version: 0.7.91 -Release: 31 +Release: 32 Summary: Trace the Library and System Calls a Program Makes License: GPLv2+ @@ -30,6 +30,10 @@ Patch9001: bugfix-0001-ltrace-byteswap-instruction-in-arm-be8-mode.patch Patch9002: bugfix-for-use-after-free-about-soname.patch Patch9003: fix-null-directive-argument.patch Patch9004: Initialize-nrhs-to-avoid-gcc-warning.patch +Patch9005: add-loongarch-support-not-upstream-makefile.patch +Patch9006: add-loongarch-support-not-upstream-sysdeps.patch +Patch9007: add-sw_64-support-not-upstream-makefile.patch +Patch9008: add-sw_64-support-not-upstream-sysdeps.patch BuildRequires: elfutils-devel dejagnu libselinux-devel autoconf automake libtool @@ -55,6 +59,10 @@ Help document for the ltrace package. %autosetup -n %{name}-%{version} -p1 %build +%ifarch loongarch64 sw_64 +%_update_config_guess +%_update_config_sub +%endif autoreconf -i %configure --docdir=%{?_pkgdocdir}%{!?_pkgdocdir:%{_docdir}/%{name}-%{version}} %make_build @@ -75,6 +83,9 @@ autoreconf -i %{_mandir}/man5/ltrace.conf.5* %changelog +* Tue Aug 29 2023 herengui - 0.7.91-32 +- add support for loongarch64 and sw_64 + * Mon Jan 11 2021 lingsheng - 0.7.91-31 - Initialize 'nrhs' to avoid gcc warning