Signed-off-by: Max Filippov <[email protected]>
---
 configure.ac                          |   2 +
 proc.c                                |   2 +-
 sysdeps/linux-gnu/Makefile.am         |   2 +-
 sysdeps/linux-gnu/xtensa/Makefile.am  |  35 ++++
 sysdeps/linux-gnu/xtensa/arch.h       |  69 +++++++
 sysdeps/linux-gnu/xtensa/breakpoint.c |  71 +++++++
 sysdeps/linux-gnu/xtensa/plt.c        | 192 ++++++++++++++++++
 sysdeps/linux-gnu/xtensa/ptrace.h     |  21 ++
 sysdeps/linux-gnu/xtensa/regs.c       |  52 +++++
 sysdeps/linux-gnu/xtensa/signalent.h  |  52 +++++
 sysdeps/linux-gnu/xtensa/syscallent.h | 357 ++++++++++++++++++++++++++++++++++
 sysdeps/linux-gnu/xtensa/trace.c      | 100 ++++++++++
 12 files changed, 953 insertions(+), 2 deletions(-)
 create mode 100644 sysdeps/linux-gnu/xtensa/Makefile.am
 create mode 100644 sysdeps/linux-gnu/xtensa/arch.h
 create mode 100644 sysdeps/linux-gnu/xtensa/breakpoint.c
 create mode 100644 sysdeps/linux-gnu/xtensa/plt.c
 create mode 100644 sysdeps/linux-gnu/xtensa/ptrace.h
 create mode 100644 sysdeps/linux-gnu/xtensa/regs.c
 create mode 100644 sysdeps/linux-gnu/xtensa/signalent.h
 create mode 100644 sysdeps/linux-gnu/xtensa/syscallent.h
 create mode 100644 sysdeps/linux-gnu/xtensa/trace.c

diff --git a/configure.ac b/configure.ac
index 4f360c8..55c5c84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,7 @@ case "${host_cpu}" in
     sun4u|sparc64)     HOST_CPU="sparc" ;;
     s390x)             HOST_CPU="s390" ;;
     i?86|x86_64)       HOST_CPU="x86" ;;
+    xtensa*)           HOST_CPU="xtensa" ;;
     *)                 HOST_CPU="${host_cpu}" ;;
 esac
 AC_SUBST(HOST_CPU)
@@ -412,6 +413,7 @@ AC_CONFIG_FILES([
        sysdeps/linux-gnu/s390/Makefile
        sysdeps/linux-gnu/sparc/Makefile
        sysdeps/linux-gnu/x86/Makefile
+       sysdeps/linux-gnu/xtensa/Makefile
        testsuite/Makefile
        testsuite/ltrace.main/Makefile
        testsuite/ltrace.minor/Makefile
diff --git a/proc.c b/proc.c
index 5385510..cc0b150 100644
--- a/proc.c
+++ b/proc.c
@@ -813,7 +813,7 @@ breakpoint_for_symbol(struct library_symbol *libsym, struct 
process *proc)
                 *   
http://lists.alioth.debian.org/pipermail/ltrace-devel/2012-November/000764.html
                 *   
http://lists.alioth.debian.org/pipermail/ltrace-devel/2012-November/000770.html
                 */
-#ifndef __mips__
+#if !defined(__mips__) && !defined(__xtensa__)
                assert(bp->libsym == NULL);
                bp->libsym = libsym;
 #endif
diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
index ec26162..857f2da 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 m68k metag mips ppc s390    \
-              sparc x86
+              sparc x86 xtensa
 
 SUBDIRS = \
        $(HOST_CPU)
diff --git a/sysdeps/linux-gnu/xtensa/Makefile.am 
b/sysdeps/linux-gnu/xtensa/Makefile.am
new file mode 100644
index 0000000..7d83ab0
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/Makefile.am
@@ -0,0 +1,35 @@
+# This file is part of ltrace.
+# Copyright (C) 2014 Cadence Design Systems Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 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 = \
+       breakpoint.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/xtensa/arch.h b/sysdeps/linux-gnu/xtensa/arch.h
new file mode 100644
index 0000000..1e85385
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/arch.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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
+ */
+
+#ifdef __XTENSA_EL__
+
+# define ARCH_ENDIAN_LITTLE
+
+# define BREAKPOINT_VALUE { 0x00, 0x40, 0x00 }
+# define DENSITY_BREAKPOINT_VALUE { 0x2d, 0xf0 }
+
+# define XTENSA_OP0_MASK 0xf
+# define XTENSA_DENSITY_FIRST 0x8
+# define XTENSA_DENSITY_LAST 0xe
+# define XTENSA_SYSCALL_MASK 0xff500f
+# define XTENSA_SYSCALL_VALUE 0x005000
+
+#elif defined(__XTENSA_EB__)
+
+# define ARCH_ENDIAN_BIG
+
+# define BREAKPOINT_VALUE { 0x00, 0x04, 0x00 }
+# define DENSITY_BREAKPOINT_VALUE { 0xd2, 0x0f }
+
+# define XTENSA_OP0_MASK 0xf0
+# define XTENSA_DENSITY_FIRST 0x80
+# define XTENSA_DENSITY_LAST 0xe0
+# define XTENSA_SYSCALL_MASK 0xf005ff00
+# define XTENSA_SYSCALL_VALUE 0x00050000
+
+#else
+# error __XTENSA_EL__ or __XTENSA_EB__ must be defined
+#endif
+
+#define BREAKPOINT_LENGTH 3
+#define DENSITY_BREAKPOINT_LENGTH 2
+
+#define DECR_PC_AFTER_BREAK 0
+
+#define LT_ELFCLASS    ELFCLASS32
+#define LT_ELF_MACHINE EM_XTENSA
+
+#define ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+};
+
+#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
+struct arch_library_symbol_data {
+       void *resolved_addr;
+};
+
+#define ARCH_HAVE_SYMBOL_RET
+#define ARCH_HAVE_ENABLE_BREAKPOINT
diff --git a/sysdeps/linux-gnu/xtensa/breakpoint.c 
b/sysdeps/linux-gnu/xtensa/breakpoint.c
new file mode 100644
index 0000000..8425d20
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/breakpoint.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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 <sys/ptrace.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "common.h"
+#include "backend.h"
+#include "sysdep.h"
+#include "breakpoint.h"
+#include "proc.h"
+#include "library.h"
+
+void
+arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
+       static unsigned char break_insn[] = BREAKPOINT_VALUE;
+       static unsigned char density_break_insn[] = DENSITY_BREAKPOINT_VALUE;
+       unsigned char *bytes;
+       long a;
+
+       debug(DEBUG_PROCESS,
+             "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
+             pid, sbp->addr, breakpoint_name(sbp));
+
+       a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
+       if (a == -1 && errno) {
+               fprintf(stderr, "enable_breakpoint"
+                       " pid=%d, addr=%p, symbol=%s: %s\n",
+                       pid, sbp->addr, breakpoint_name(sbp),
+                       strerror(errno));
+               return;
+       }
+       bytes = (unsigned char *)&a;
+       memcpy(sbp->orig_value, bytes, BREAKPOINT_LENGTH);
+       if ((bytes[0] & XTENSA_OP0_MASK) >= XTENSA_DENSITY_FIRST &&
+           (bytes[0] & XTENSA_OP0_MASK) < XTENSA_DENSITY_LAST) {
+               memcpy(bytes, density_break_insn, DENSITY_BREAKPOINT_LENGTH);
+       } else {
+               memcpy(bytes, break_insn, BREAKPOINT_LENGTH);
+       }
+       a = ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
+       if (a == -1) {
+               fprintf(stderr, "enable_breakpoint"
+                       " pid=%d, addr=%p, symbol=%s: %s\n",
+                       pid, sbp->addr, breakpoint_name(sbp),
+                       strerror(errno));
+               return;
+       }
+}
diff --git a/sysdeps/linux-gnu/xtensa/plt.c b/sysdeps/linux-gnu/xtensa/plt.c
new file mode 100644
index 0000000..51a6296
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/plt.c
@@ -0,0 +1,192 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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 <errno.h>
+#include <error.h>
+#include <gelf.h>
+#include <string.h>
+#include <sys/ptrace.h>
+
+#include "common.h"
+#include "debug.h"
+#include "proc.h"
+#include "library.h"
+#include "breakpoint.h"
+#include "backend.h"
+
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+       Elf_Scn *scn;
+       GElf_Shdr shdr;
+
+       if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
+           || scn == NULL) {
+       fail:
+               error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
+                     elf_errmsg(-1));
+               return -1;
+       }
+
+       Elf_Data *data = elf_loaddata(scn, &shdr);
+       if (data == NULL)
+               goto fail;
+
+       size_t i;
+       GElf_Addr relplt_addr;
+       GElf_Xword relplt_size;
+
+       for (i = 0; i < shdr.sh_size / shdr.sh_entsize; ++i) {
+               GElf_Dyn dyn;
+
+               if (gelf_getdyn(data, i, &dyn) == NULL)
+                       goto fail;
+
+               if (dyn.d_tag == DT_JMPREL) {
+                       relplt_addr = dyn.d_un.d_ptr;
+               } else if (dyn.d_tag == DT_PLTRELSZ) {
+                       relplt_size = dyn.d_un.d_val;
+               }
+       }
+
+       for (i = 1; i < lte->ehdr.e_shnum; ++i) {
+               Elf_Scn *scn;
+               GElf_Shdr shdr;
+
+               scn = elf_getscn(lte->elf, i);
+               if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
+                       fprintf(stderr, "Couldn't get section header: %s\n",
+                               elf_errmsg(-1));
+                       exit(EXIT_FAILURE);
+               }
+               if (shdr.sh_addr == relplt_addr
+                   && shdr.sh_size == relplt_size) {
+                       if (elf_read_relocs(lte, scn, &shdr,
+                                           &lte->plt_relocs) < 0) {
+                               fprintf(stderr, "Couldn't get .rel*.plt"
+                                       " data: %s\n", elf_errmsg(-1));
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+}
+
+GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
+{
+       return rela->r_offset;
+}
+
+void *sym2addr(struct process *proc, struct library_symbol *sym)
+{
+       void *addr = NULL;
+       long ret;
+
+       switch (sym->plt_type) {
+       case LS_TOPLT_NONE:
+               addr = sym->enter_addr + 3;
+               break;
+
+       case LS_TOPLT_EXEC:
+               ret = ptrace(PTRACE_PEEKTEXT, proc->pid, sym->enter_addr, 0);
+               addr = ret == -1 ? NULL : (void *)(ret + 3);
+               break;
+       }
+       if (sym->arch.resolved_addr == NULL)
+               sym->arch.resolved_addr = addr;
+       return addr;
+}
+
+int
+arch_library_symbol_init(struct library_symbol *libsym)
+{
+       libsym->arch.resolved_addr = NULL;
+       return 0;
+}
+
+void
+arch_library_symbol_destroy(struct library_symbol *libsym)
+{
+}
+
+int
+arch_library_symbol_clone(struct library_symbol *retp,
+                         struct library_symbol *libsym)
+{
+       retp->arch = libsym->arch;
+       return 0;
+}
+
+void arch_symbol_ret(struct process *proc, struct library_symbol *libsym)
+{
+       struct breakpoint *bp;
+       arch_addr_t resolved_addr;
+       struct process *leader = proc->leader;
+
+       resolved_addr = sym2addr(proc, libsym);
+
+       if (libsym->arch.resolved_addr == resolved_addr)
+               return;
+
+       /* Delete breakpoint at PLT entry: PLT entry still may be called
+        * if the compiler decided to cache the function address before
+        * it was resolved, but such calls will never be removed from the
+        * ltrace call stack, because both breakpoints (at PLT entry and
+        * at the function itself) are associated with the same struct
+        * library_symbol.  */
+
+       delete_breakpoint_at(proc, libsym->arch.resolved_addr);
+       libsym->arch.resolved_addr = resolved_addr;
+
+       if (DICT_HAS_KEY(proc->breakpoints, &resolved_addr)) {
+               return;
+       }
+
+       bp = malloc(sizeof (*bp));
+       if (bp == NULL) {
+               fprintf(stderr, "Failed to allocate bp for %s\n",
+                       libsym->name);
+               return;
+       }
+
+       if (breakpoint_init(bp, leader, resolved_addr, libsym) < 0)
+               goto err;
+
+       if (proc_add_breakpoint(leader, bp) < 0) {
+               breakpoint_destroy(bp);
+               goto err;
+       }
+
+       if (breakpoint_turn_on(bp, leader) < 0) {
+               proc_remove_breakpoint(leader, bp);
+               breakpoint_destroy(bp);
+               goto err;
+       }
+       return;
+err:
+       free(bp);
+}
diff --git a/sysdeps/linux-gnu/xtensa/ptrace.h 
b/sysdeps/linux-gnu/xtensa/ptrace.h
new file mode 100644
index 0000000..6e67fff
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/ptrace.h
@@ -0,0 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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 <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/xtensa/regs.c b/sysdeps/linux-gnu/xtensa/regs.c
new file mode 100644
index 0000000..b07d331
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/regs.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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 <sys/types.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "proc.h"
+#include "common.h"
+
+void *get_instruction_pointer(struct process *proc)
+{
+       int retval = ptrace(PTRACE_PEEKUSER, proc->pid, REG_PC, 0);
+       return (void *)retval;
+}
+
+void set_instruction_pointer(struct process *proc, void *addr)
+{
+       ptrace(PTRACE_POKEUSER, proc->pid, REG_PC, addr);
+}
+
+void *get_stack_pointer(struct process *proc)
+{
+       int retval = ptrace(PTRACE_PEEKUSER, proc->pid, (REG_A_BASE + 1), 0);
+       return (void *)retval;
+}
+
+void *get_return_addr(struct process *proc, void *stack_pointer)
+{
+       unsigned int retval = ptrace(PTRACE_PEEKUSER, proc->pid, (REG_A_BASE + 
0), 0);
+       /* Assume call8, mask the upper 2 bits. */
+       return (void *)(0x3FFFFFFF & retval);
+}
diff --git a/sysdeps/linux-gnu/xtensa/signalent.h 
b/sysdeps/linux-gnu/xtensa/signalent.h
new file mode 100644
index 0000000..953534d
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/signalent.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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/xtensa/syscallent.h 
b/sysdeps/linux-gnu/xtensa/syscallent.h
new file mode 100644
index 0000000..ff19d83
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/syscallent.h
@@ -0,0 +1,357 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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
+ */
+
+       "spill",                           /* 0 */
+       "xtensa",                          /* 1 */
+       "available4",                      /* 2 */
+       "available5",                      /* 3 */
+       "available6",                      /* 4 */
+       "available7",                      /* 5 */
+       "available8",                      /* 6 */
+       "available9",                      /* 7 */
+       "open",                            /* 8 */
+       "close",                           /* 9 */
+       "dup",                             /* 10 */
+       "dup2",                            /* 11 */
+       "read",                            /* 12 */
+       "write",                           /* 13 */
+       "select",                          /* 14 */
+       "lseek",                           /* 15 */
+       "poll",                            /* 16 */
+       "_llseek",                         /* 17 */
+       "epoll_wait",                      /* 18 */
+       "epoll_ctl",                       /* 19 */
+       "epoll_create",                    /* 20 */
+       "creat",                           /* 21 */
+       "truncate",                        /* 22 */
+       "ftruncate",                       /* 23 */
+       "readv",                           /* 24 */
+       "writev",                          /* 25 */
+       "fsync",                           /* 26 */
+       "fdatasync",                       /* 27 */
+       "truncate64",                      /* 28 */
+       "ftruncate64",                     /* 29 */
+       "pread64",                         /* 30 */
+       "pwrite64",                        /* 31 */
+       "link",                            /* 32 */
+       "rename",                          /* 33 */
+       "symlink",                         /* 34 */
+       "readlink",                        /* 35 */
+       "mknod",                           /* 36 */
+       "pipe",                            /* 37 */
+       "unlink",                          /* 38 */
+       "rmdir",                           /* 39 */
+       "mkdir",                           /* 40 */
+       "chdir",                           /* 41 */
+       "fchdir",                          /* 42 */
+       "getcwd",                          /* 43 */
+       "chmod",                           /* 44 */
+       "chown",                           /* 45 */
+       "stat",                            /* 46 */
+       "stat64",                          /* 47 */
+       "lchown",                          /* 48 */
+       "lstat",                           /* 49 */
+       "lstat64",                         /* 50 */
+       "available51",                     /* 51 */
+       "fchmod",                          /* 52 */
+       "fchown",                          /* 53 */
+       "fstat",                           /* 54 */
+       "fstat64",                         /* 55 */
+       "flock",                           /* 56 */
+       "access",                          /* 57 */
+       "umask",                           /* 58 */
+       "getdents",                        /* 59 */
+       "getdents64",                      /* 60 */
+       "fcntl64",                         /* 61 */
+       "available62",                     /* 62 */
+       "fadvise64_64",                    /* 63 */
+       "utime",                           /* 64 */
+       "utimes",                          /* 65 */
+       "ioctl",                           /* 66 */
+       "fcntl",                           /* 67 */
+       "setxattr",                        /* 68 */
+       "getxattr",                        /* 69 */
+       "listxattr",                       /* 70 */
+       "removexattr",                     /* 71 */
+       "lsetxattr",                       /* 72 */
+       "lgetxattr",                       /* 73 */
+       "llistxattr",                      /* 74 */
+       "lremovexattr",                    /* 75 */
+       "fsetxattr",                       /* 76 */
+       "fgetxattr",                       /* 77 */
+       "flistxattr",                      /* 78 */
+       "fremovexattr",                    /* 79 */
+       "mmap2",                           /* 80 */
+       "munmap",                          /* 81 */
+       "mprotect",                        /* 82 */
+       "brk",                             /* 83 */
+       "mlock",                           /* 84 */
+       "munlock",                         /* 85 */
+       "mlockall",                        /* 86 */
+       "munlockall",                      /* 87 */
+       "mremap",                          /* 88 */
+       "msync",                           /* 89 */
+       "mincore",                         /* 90 */
+       "madvise",                         /* 91 */
+       "shmget",                          /* 92 */
+       "shmat",                           /* 93 */
+       "shmctl",                          /* 94 */
+       "shmdt",                           /* 95 */
+       "socket",                          /* 96 */
+       "setsockopt",                      /* 97 */
+       "getsockopt",                      /* 98 */
+       "shutdown",                        /* 99 */
+       "bind",                            /* 100 */
+       "connect",                         /* 101 */
+       "listen",                          /* 102 */
+       "accept",                          /* 103 */
+       "getsockname",                     /* 104 */
+       "getpeername",                     /* 105 */
+       "sendmsg",                         /* 106 */
+       "recvmsg",                         /* 107 */
+       "send",                            /* 108 */
+       "recv",                            /* 109 */
+       "sendto",                          /* 110 */
+       "recvfrom",                        /* 111 */
+       "socketpair",                      /* 112 */
+       "sendfile",                        /* 113 */
+       "sendfile64",                      /* 114 */
+       "sendmmsg",                        /* 115 */
+       "clone",                           /* 116 */
+       "execve",                          /* 117 */
+       "exit",                            /* 118 */
+       "exit_group",                      /* 119 */
+       "getpid",                          /* 120 */
+       "wait4",                           /* 121 */
+       "waitid",                          /* 122 */
+       "kill",                            /* 123 */
+       "tkill",                           /* 124 */
+       "tgkill",                          /* 125 */
+       "set_tid_address",                 /* 126 */
+       "gettid",                          /* 127 */
+       "setsid",                          /* 128 */
+       "getsid",                          /* 129 */
+       "prctl",                           /* 130 */
+       "personality",                     /* 131 */
+       "getpriority",                     /* 132 */
+       "setpriority",                     /* 133 */
+       "setitimer",                       /* 134 */
+       "getitimer",                       /* 135 */
+       "setuid",                          /* 136 */
+       "getuid",                          /* 137 */
+       "setgid",                          /* 138 */
+       "getgid",                          /* 139 */
+       "geteuid",                         /* 140 */
+       "getegid",                         /* 141 */
+       "setreuid",                        /* 142 */
+       "setregid",                        /* 143 */
+       "setresuid",                       /* 144 */
+       "getresuid",                       /* 145 */
+       "setresgid",                       /* 146 */
+       "getresgid",                       /* 147 */
+       "setpgid",                         /* 148 */
+       "getpgid",                         /* 149 */
+       "getppid",                         /* 150 */
+       "getpgrp",                         /* 151 */
+       "reserved152",                     /* 152 */
+       "reserved153",                     /* 153 */
+       "times",                           /* 154 */
+       "acct",                            /* 155 */
+       "sched_setaffinity",               /* 156 */
+       "sched_getaffinity",               /* 157 */
+       "capget",                          /* 158 */
+       "capset",                          /* 159 */
+       "ptrace",                          /* 160 */
+       "semtimedop",                      /* 161 */
+       "semget",                          /* 162 */
+       "semop",                           /* 163 */
+       "semctl",                          /* 164 */
+       "available165",                    /* 165 */
+       "msgget",                          /* 166 */
+       "msgsnd",                          /* 167 */
+       "msgrcv",                          /* 168 */
+       "msgctl",                          /* 169 */
+       "available170",                    /* 170 */
+       "umount2",                         /* 171 */
+       "mount",                           /* 172 */
+       "swapon",                          /* 173 */
+       "chroot",                          /* 174 */
+       "pivot_root",                      /* 175 */
+       "umount",                          /* 176 */
+       "swapoff",                         /* 177 */
+       "sync",                            /* 178 */
+       "syncfs",                          /* 179 */
+       "setfsuid",                        /* 180 */
+       "setfsgid",                        /* 181 */
+       "sysfs",                           /* 182 */
+       "ustat",                           /* 183 */
+       "statfs",                          /* 184 */
+       "fstatfs",                         /* 185 */
+       "statfs64",                        /* 186 */
+       "fstatfs64",                       /* 187 */
+       "setrlimit",                       /* 188 */
+       "getrlimit",                       /* 189 */
+       "getrusage",                       /* 190 */
+       "futex",                           /* 191 */
+       "gettimeofday",                    /* 192 */
+       "settimeofday",                    /* 193 */
+       "adjtimex",                        /* 194 */
+       "nanosleep",                       /* 195 */
+       "getgroups",                       /* 196 */
+       "setgroups",                       /* 197 */
+       "sethostname",                     /* 198 */
+       "setdomainname",                   /* 199 */
+       "syslog",                          /* 200 */
+       "vhangup",                         /* 201 */
+       "uselib",                          /* 202 */
+       "reboot",                          /* 203 */
+       "quotactl",                        /* 204 */
+       "nfsservctl",                      /* 205 */
+       "_sysctl",                         /* 206 */
+       "bdflush",                         /* 207 */
+       "uname",                           /* 208 */
+       "sysinfo",                         /* 209 */
+       "init_module",                     /* 210 */
+       "delete_module",                   /* 211 */
+       "sched_setparam",                  /* 212 */
+       "sched_getparam",                  /* 213 */
+       "sched_setscheduler",              /* 214 */
+       "sched_getscheduler",              /* 215 */
+       "sched_get_priority_max",          /* 216 */
+       "sched_get_priority_min",          /* 217 */
+       "sched_rr_get_interval",           /* 218 */
+       "sched_yield",                     /* 219 */
+       "220",                             /* 220 */
+       "221",                             /* 221 */
+       "available222",                    /* 222 */
+       "restart_syscall",                 /* 223 */
+       "sigaltstack",                     /* 224 */
+       "rt_sigreturn",                    /* 225 */
+       "rt_sigaction",                    /* 226 */
+       "rt_sigprocmask",                  /* 227 */
+       "rt_sigpending",                   /* 228 */
+       "rt_sigtimedwait",                 /* 229 */
+       "rt_sigqueueinfo",                 /* 230 */
+       "rt_sigsuspend",                   /* 231 */
+       "mq_open",                         /* 232 */
+       "mq_unlink",                       /* 233 */
+       "mq_timedsend",                    /* 234 */
+       "mq_timedreceive",                 /* 235 */
+       "mq_notify",                       /* 236 */
+       "mq_getsetattr",                   /* 237 */
+       "available238",                    /* 238 */
+       "io_setup",                        /* 239 */
+       "io_destroy",                      /* 240 */
+       "io_submit",                       /* 241 */
+       "io_getevents",                    /* 242 */
+       "io_cancel",                       /* 243 */
+       "clock_settime",                   /* 244 */
+       "clock_gettime",                   /* 245 */
+       "clock_getres",                    /* 246 */
+       "clock_nanosleep",                 /* 247 */
+       "timer_create",                    /* 248 */
+       "timer_delete",                    /* 249 */
+       "timer_settime",                   /* 250 */
+       "timer_gettime",                   /* 251 */
+       "timer_getoverrun",                /* 252 */
+       "reserved253",                     /* 253 */
+       "lookup_dcookie",                  /* 254 */
+       "available255",                    /* 255 */
+       "add_key",                         /* 256 */
+       "request_key",                     /* 257 */
+       "keyctl",                          /* 258 */
+       "available259",                    /* 259 */
+       "readahead",                       /* 260 */
+       "remap_file_pages",                /* 261 */
+       "migrate_pages",                   /* 262 */
+       "mbind",                           /* 263 */
+       "get_mempolicy",                   /* 264 */
+       "set_mempolicy",                   /* 265 */
+       "unshare",                         /* 266 */
+       "move_pages",                      /* 267 */
+       "splice",                          /* 268 */
+       "tee",                             /* 269 */
+       "vmsplice",                        /* 270 */
+       "available271",                    /* 271 */
+       "pselect6",                        /* 272 */
+       "ppoll",                           /* 273 */
+       "epoll_pwait",                     /* 274 */
+       "epoll_create1",                   /* 275 */
+       "inotify_init",                    /* 276 */
+       "inotify_add_watch",               /* 277 */
+       "inotify_rm_watch",                /* 278 */
+       "inotify_init1",                   /* 279 */
+       "getcpu",                          /* 280 */
+       "kexec_load",                      /* 281 */
+       "ioprio_set",                      /* 282 */
+       "ioprio_get",                      /* 283 */
+       "set_robust_list",                 /* 284 */
+       "get_robust_list",                 /* 285 */
+       "available286",                    /* 286 */
+       "available287",                    /* 287 */
+       "openat",                          /* 288 */
+       "mkdirat",                         /* 289 */
+       "mknodat",                         /* 290 */
+       "unlinkat",                        /* 291 */
+       "renameat",                        /* 292 */
+       "linkat",                          /* 293 */
+       "symlinkat",                       /* 294 */
+       "readlinkat",                      /* 295 */
+       "utimensat",                       /* 296 */
+       "fchownat",                        /* 297 */
+       "futimesat",                       /* 298 */
+       "fstatat64",                       /* 299 */
+       "fchmodat",                        /* 300 */
+       "faccessat",                       /* 301 */
+       "available302",                    /* 302 */
+       "available303",                    /* 303 */
+       "signalfd",                        /* 304 */
+       "305",                             /* 305 */
+       "eventfd",                         /* 306 */
+       "recvmmsg",                        /* 307 */
+       "setns",                           /* 308 */
+       "signalfd4",                       /* 309 */
+       "dup3",                            /* 310 */
+       "pipe2",                           /* 311 */
+       "timerfd_create",                  /* 312 */
+       "timerfd_settime",                 /* 313 */
+       "timerfd_gettime",                 /* 314 */
+       "available315",                    /* 315 */
+       "eventfd2",                        /* 316 */
+       "preadv",                          /* 317 */
+       "pwritev",                         /* 318 */
+       "available319",                    /* 319 */
+       "fanotify_init",                   /* 320 */
+       "fanotify_mark",                   /* 321 */
+       "process_vm_readv",                /* 322 */
+       "process_vm_writev",               /* 323 */
+       "name_to_handle_at",               /* 324 */
+       "open_by_handle_at",               /* 325 */
+       "sync_file_range",                 /* 326 */
+       "perf_event_open",                 /* 327 */
+       "rt_tgsigqueueinfo",               /* 328 */
+       "clock_adjtime",                   /* 329 */
+       "prlimit64",                       /* 330 */
+       "kcmp",                            /* 331 */
+       "finit_module",                    /* 332 */
+       "accept4",                         /* 333 */
+       "sched_setattr",                   /* 334 */
+       "sched_getattr",                   /* 335 */
+       "syscall_count",                   /* 336 */
diff --git a/sysdeps/linux-gnu/xtensa/trace.c b/sysdeps/linux-gnu/xtensa/trace.c
new file mode 100644
index 0000000..0fbcfcb
--- /dev/null
+++ b/sysdeps/linux-gnu/xtensa/trace.c
@@ -0,0 +1,100 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 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 <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "common.h"
+#include "proc.h"
+
+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)) {
+               /* get the user's pc */
+               int pc = ptrace(PTRACE_PEEKUSER, proc->pid, REG_PC, 0);
+
+               /* fetch the SWI instruction */
+               int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 3, 0);
+
+               *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, SYSCALL_NR, 0);
+               /* if it is a syscall, return 1 or 2 */
+               if ((insn & XTENSA_SYSCALL_MASK) == XTENSA_SYSCALL_VALUE) {
+                       if ((proc->callstack_depth > 0)
+                           && proc->callstack[proc->callstack_depth
+                                              - 1].is_syscall) {
+                               return 2;
+                       } else {
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+long gimme_arg(enum tof type, struct process *proc, int arg_num)
+{
+       /* Deal with the Xtensa calling conventions.  Function calls
+        * and system calls have different ABIs.  */
+       /* Assume call8 for function calls.  */
+       if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
+               if (arg_num == -1) /* return value */
+                       return ptrace(PTRACE_PEEKUSER, proc->pid,
+                                     (REG_A_BASE + 10), 0);
+               else if (arg_num < 6) {
+                       int regnr;
+                       regnr = REG_A_BASE + 2 + arg_num;
+                       return ptrace(PTRACE_PEEKUSER, proc->pid, regnr, 0);
+               } else
+                       return ptrace(PTRACE_PEEKDATA, proc->pid,
+                                     proc->stack_pointer
+                                     + 4 * (arg_num - 6), 0);
+       } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
+               if (arg_num == -1) /* return value */
+                       return ptrace(PTRACE_PEEKUSER, proc->pid,
+                                     (REG_A_BASE + 2), 0);
+               if (arg_num < 6) {
+                       int regnr;
+                       regnr = REG_A_BASE
+                               + ((arg_num == 0)
+                                  ? 6 : arg_num + ((arg_num >= 4) ? 4 : 2));
+                       return ptrace(PTRACE_PEEKUSER, proc->pid, regnr, 0);
+               } else
+                       return ptrace(PTRACE_PEEKDATA, proc->pid,
+                                     proc->stack_pointer + 4 * (arg_num - 6),
+                                     0);
+       } else {
+               fprintf(stderr, "gimme_arg called with wrong arguments\n");
+               return -1;
+       }
+
+       return 0;
+}
-- 
1.8.1.4


_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to